Implement support for unregistering objects

refs #9101
This commit is contained in:
Gunnar Beutner 2015-08-13 09:02:52 +02:00
parent f405a26052
commit e2290d5012
27 changed files with 363 additions and 80 deletions

View File

@ -177,6 +177,14 @@ void DynamicObject::Register(void)
dtype->RegisterObject(this); dtype->RegisterObject(this);
} }
void DynamicObject::Unregister(void)
{
ASSERT(!OwnsLock());
DynamicType::Ptr dtype = GetType();
dtype->UnregisterObject(this);
}
void DynamicObject::Start(void) void DynamicObject::Start(void)
{ {
ASSERT(!OwnsLock()); ASSERT(!OwnsLock());

View File

@ -58,6 +58,7 @@ public:
bool IsAttributeModified(const String& attr) const; bool IsAttributeModified(const String& attr) const;
void Register(void); void Register(void);
void Unregister(void);
void Activate(void); void Activate(void);
void Deactivate(void); void Deactivate(void);

View File

@ -34,6 +34,7 @@ enum HAMode
class NameComposer { class NameComposer {
public: public:
virtual String MakeName(const String& shortName, const Object::Ptr& context) const = 0; virtual String MakeName(const String& shortName, const Object::Ptr& context) const = 0;
virtual Dictionary::Ptr ParseName(const String& name) const = 0;
}; };
}}} }}}

View File

@ -113,6 +113,18 @@ void DynamicType::RegisterObject(const DynamicObject::Ptr& object)
} }
} }
void DynamicType::UnregisterObject(const DynamicObject::Ptr& object)
{
String name = object->GetName();
{
ObjectLock olock(this);
m_ObjectMap.erase(name);
m_ObjectVector.erase(std::remove(m_ObjectVector.begin(), m_ObjectVector.end(), object), m_ObjectVector.end());
}
}
DynamicObject::Ptr DynamicType::GetObject(const String& name) const DynamicObject::Ptr DynamicType::GetObject(const String& name) const
{ {
ObjectLock olock(this); ObjectLock olock(this);

View File

@ -46,6 +46,7 @@ public:
DynamicObject::Ptr GetObject(const String& name) const; DynamicObject::Ptr GetObject(const String& name) const;
void RegisterObject(const DynamicObject::Ptr& object); void RegisterObject(const DynamicObject::Ptr& object);
void UnregisterObject(const DynamicObject::Ptr& object);
static std::vector<DynamicType::Ptr> GetTypes(void); static std::vector<DynamicType::Ptr> GetTypes(void);
std::pair<DynamicTypeIterator<DynamicObject>, DynamicTypeIterator<DynamicObject> > GetObjects(void); std::pair<DynamicTypeIterator<DynamicObject>, DynamicTypeIterator<DynamicObject> > GetObjects(void);

View File

@ -56,6 +56,16 @@ Type::Ptr Type::GetByName(const String& name)
return ptype; return ptype;
} }
String Type::GetPluralName(void) const
{
String name = GetName();
if (name[name.GetLength() - 1] == 'y')
return name.SubStr(0, name.GetLength() - 1) + "ies";
else
return name + "s";
}
Object::Ptr Type::Instantiate(void) const Object::Ptr Type::Instantiate(void) const
{ {
ObjectFactory factory = GetFactory(); ObjectFactory factory = GetFactory();

View File

@ -80,6 +80,8 @@ public:
virtual Field GetFieldInfo(int id) const = 0; virtual Field GetFieldInfo(int id) const = 0;
virtual int GetFieldCount(void) const = 0; virtual int GetFieldCount(void) const = 0;
String GetPluralName(void) const;
Object::Ptr Instantiate(void) const; Object::Ptr Instantiate(void) const;
bool IsAssignableFrom(const Type::Ptr& other) const; bool IsAssignableFrom(const Type::Ptr& other) const;

View File

@ -258,11 +258,15 @@ int DaemonCommand::Run(const po::variables_map& vm, const std::vector<std::strin
} }
} }
{
WorkQueue upq(25000, Application::GetConcurrency());
// activate config only after daemonization: it starts threads and that is not compatible with fork() // activate config only after daemonization: it starts threads and that is not compatible with fork()
if (!ConfigItem::ActivateItems()) { if (!ConfigItem::ActivateItems(upq, true)) {
Log(LogCritical, "cli", "Error activating configuration."); Log(LogCritical, "cli", "Error activating configuration.");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
}
if (vm.count("daemonize")) { if (vm.count("daemonize")) {
String errorLog; String errorLog;

View File

@ -123,7 +123,8 @@ bool DaemonUtility::LoadConfigFiles(const std::vector<std::string>& configs,
if (!DaemonUtility::ValidateConfigFiles(configs, objectsFile)) if (!DaemonUtility::ValidateConfigFiles(configs, objectsFile))
return false; return false;
bool result = ConfigItem::CommitItems(); WorkQueue upq(25000, Application::GetConcurrency());
bool result = ConfigItem::CommitItems(upq);
if (!result) if (!result)
return false; return false;

View File

@ -268,6 +268,19 @@ void ConfigItem::Register(void)
} }
} }
/**
* Unregisters the configuration item.
*/
void ConfigItem::Unregister(void)
{
if (m_Object)
m_Object->Unregister();
boost::mutex::scoped_lock lock(m_Mutex);
m_UnnamedItems.erase(std::remove(m_UnnamedItems.begin(), m_UnnamedItems.end(), this), m_UnnamedItems.end());
m_Items[m_Type].erase(m_Name);
}
/** /**
* Retrieves a configuration item by type and name. * Retrieves a configuration item by type and name.
* *
@ -292,7 +305,7 @@ ConfigItem::Ptr ConfigItem::GetObject(const String& type, const String& name)
return it2->second; return it2->second;
} }
bool ConfigItem::CommitNewItems(WorkQueue& upq) bool ConfigItem::CommitNewItems(WorkQueue& upq, std::vector<ConfigItem::Ptr>& newItems)
{ {
typedef std::pair<ConfigItem::Ptr, bool> ItemPair; typedef std::pair<ConfigItem::Ptr, bool> ItemPair;
std::vector<ItemPair> items; std::vector<ItemPair> items;
@ -320,6 +333,7 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq)
return true; return true;
BOOST_FOREACH(const ItemPair& ip, items) { BOOST_FOREACH(const ItemPair& ip, items) {
newItems.push_back(ip.first);
upq.Enqueue(boost::bind(&ConfigItem::Commit, ip.first, ip.second)); upq.Enqueue(boost::bind(&ConfigItem::Commit, ip.first, ip.second));
} }
@ -398,7 +412,7 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq)
if (upq.HasExceptions()) if (upq.HasExceptions())
return false; return false;
if (!CommitNewItems(upq)) if (!CommitNewItems(upq, newItems))
return false; return false;
} }
} }
@ -406,32 +420,42 @@ bool ConfigItem::CommitNewItems(WorkQueue& upq)
return true; return true;
} }
bool ConfigItem::CommitItems(void) bool ConfigItem::CommitItems(WorkQueue& upq)
{ {
WorkQueue upq(25000, Application::GetConcurrency());
Log(LogInformation, "ConfigItem", "Committing config items"); Log(LogInformation, "ConfigItem", "Committing config items");
if (!CommitNewItems(upq)) { std::vector<ConfigItem::Ptr> newItems;
if (!CommitNewItems(upq, newItems)) {
upq.ReportExceptions("config"); upq.ReportExceptions("config");
BOOST_FOREACH(const ConfigItem::Ptr& item, newItems) {
item->Unregister();
}
return false; return false;
} }
ApplyRule::CheckMatches(); ApplyRule::CheckMatches();
/* log stats for external parsers */ /* log stats for external parsers */
BOOST_FOREACH(const DynamicType::Ptr& type, DynamicType::GetTypes()) { typedef std::map<Type::Ptr, int> ItemCountMap;
int count = std::distance(type->GetObjects().first, type->GetObjects().second); ItemCountMap itemCounts;
if (count > 0) BOOST_FOREACH(const ConfigItem::Ptr& item, newItems) {
itemCounts[item->m_Object->GetReflectionType()]++;
}
BOOST_FOREACH(const ItemCountMap::value_type& kv, itemCounts) {
Log(LogInformation, "ConfigItem") Log(LogInformation, "ConfigItem")
<< "Checked " << count << " " << type->GetName() << "(s)."; << "Instantiated " << kv.second << " " << kv.first->GetPluralName() << ".";
} }
return true; return true;
} }
bool ConfigItem::ActivateItems(void) bool ConfigItem::ActivateItems(WorkQueue& upq, bool restoreState)
{ {
if (restoreState) {
/* restore the previous program state */ /* restore the previous program state */
try { try {
DynamicObject::RestoreObjects(Application::GetStatePath()); DynamicObject::RestoreObjects(Application::GetStatePath());
@ -439,11 +463,10 @@ bool ConfigItem::ActivateItems(void)
Log(LogCritical, "ConfigItem") Log(LogCritical, "ConfigItem")
<< "Failed to restore state file: " << DiagnosticInformation(ex); << "Failed to restore state file: " << DiagnosticInformation(ex);
} }
}
Log(LogInformation, "ConfigItem", "Triggering Start signal for config items"); Log(LogInformation, "ConfigItem", "Triggering Start signal for config items");
WorkQueue upq(25000, Application::GetConcurrency());
BOOST_FOREACH(const DynamicType::Ptr& type, DynamicType::GetTypes()) { BOOST_FOREACH(const DynamicType::Ptr& type, DynamicType::GetTypes()) {
BOOST_FOREACH(const DynamicObject::Ptr& object, type->GetObjects()) { BOOST_FOREACH(const DynamicObject::Ptr& object, type->GetObjects()) {
if (object->IsActive()) if (object->IsActive())
@ -481,40 +504,11 @@ bool ConfigItem::CommitAndActivate(void)
{ {
WorkQueue upq(25000, Application::GetConcurrency()); WorkQueue upq(25000, Application::GetConcurrency());
if (!CommitNewItems(upq)) { if (!CommitItems(upq))
upq.ReportExceptions("ConfigItem");
boost::mutex::scoped_lock lock(m_Mutex);
m_Items.clear();
m_UnnamedItems.clear();
return false; return false;
}
BOOST_FOREACH(const DynamicType::Ptr& type, DynamicType::GetTypes()) {
BOOST_FOREACH(const DynamicObject::Ptr& object, type->GetObjects()) {
if (object->IsActive())
continue;
#ifdef I2_DEBUG
Log(LogDebug, "ConfigItem")
<< "Activating object '" << object->GetName() << "' of type '" << object->GetType()->GetName() << "'";
#endif /* I2_DEBUG */
upq.Enqueue(boost::bind(&DynamicObject::Activate, object));
}
}
upq.Join();
if (upq.HasExceptions()) {
upq.ReportExceptions("ConfigItem");
boost::mutex::scoped_lock lock(m_Mutex);
m_Items.clear();
m_UnnamedItems.clear();
if (!ActivateItems(upq, false))
return false; return false;
}
return true; return true;
} }

View File

@ -55,6 +55,7 @@ public:
DynamicObject::Ptr Commit(bool discard = true); DynamicObject::Ptr Commit(bool discard = true);
void Register(void); void Register(void);
void Unregister(void);
DebugInfo GetDebugInfo(void) const; DebugInfo GetDebugInfo(void) const;
Dictionary::Ptr GetScope(void) const; Dictionary::Ptr GetScope(void) const;
@ -64,8 +65,8 @@ public:
static ConfigItem::Ptr GetObject(const String& type, static ConfigItem::Ptr GetObject(const String& type,
const String& name); const String& name);
static bool CommitItems(void); static bool CommitItems(WorkQueue& upq);
static bool ActivateItems(void); static bool ActivateItems(WorkQueue& upq, bool restoreState);
static bool CommitAndActivate(void); static bool CommitAndActivate(void);
@ -97,7 +98,7 @@ private:
static ConfigItem::Ptr GetObjectUnlocked(const String& type, static ConfigItem::Ptr GetObjectUnlocked(const String& type,
const String& name); const String& name);
static bool CommitNewItems(WorkQueue& upq); static bool CommitNewItems(WorkQueue& upq, std::vector<ConfigItem::Ptr>& newItems);
}; };
} }

View File

@ -23,6 +23,8 @@
#include "base/logger.hpp" #include "base/logger.hpp"
#include "base/exception.hpp" #include "base/exception.hpp"
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
using namespace icinga; using namespace icinga;
@ -45,6 +47,27 @@ String DependencyNameComposer::MakeName(const String& shortName, const Object::P
return name; return name;
} }
Dictionary::Ptr DependencyNameComposer::ParseName(const String& name) const
{
std::vector<String> tokens;
boost::algorithm::split(tokens, name, boost::is_any_of("!"));
if (tokens.size() < 2)
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid Dependency name."));
Dictionary::Ptr result = new Dictionary();
result->Set("child_host_name", tokens[0]);
if (tokens.size() > 2) {
result->Set("child_service_name", tokens[1]);
result->Set("name", tokens[2]);
} else {
result->Set("name", tokens[1]);
}
return result;
}
void Dependency::OnConfigLoaded(void) void Dependency::OnConfigLoaded(void)
{ {
Value defaultFilter; Value defaultFilter;

View File

@ -30,6 +30,7 @@ class I2_ICINGA_API DependencyNameComposer : public NameComposer
{ {
public: public:
virtual String MakeName(const String& shortName, const Object::Ptr& context) const; virtual String MakeName(const String& shortName, const Object::Ptr& context) const;
virtual Dictionary::Ptr ParseName(const String& name) const;
}; };
}}} }}}

View File

@ -29,6 +29,8 @@
#include "base/initialize.hpp" #include "base/initialize.hpp"
#include "base/scriptglobal.hpp" #include "base/scriptglobal.hpp"
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
using namespace icinga; using namespace icinga;
@ -54,6 +56,27 @@ String NotificationNameComposer::MakeName(const String& shortName, const Object:
return name; return name;
} }
Dictionary::Ptr NotificationNameComposer::ParseName(const String& name) const
{
std::vector<String> tokens;
boost::algorithm::split(tokens, name, boost::is_any_of("!"));
if (tokens.size() < 2)
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid Notification name."));
Dictionary::Ptr result = new Dictionary();
result->Set("host_name", tokens[0]);
if (tokens.size() > 2) {
result->Set("service_name", tokens[1]);
result->Set("name", tokens[2]);
} else {
result->Set("name", tokens[1]);
}
return result;
}
void Notification::StaticInitialize(void) void Notification::StaticInitialize(void)
{ {
ScriptGlobal::Set("OK", StateFilterOK); ScriptGlobal::Set("OK", StateFilterOK);

View File

@ -29,6 +29,7 @@ class I2_ICINGA_API NotificationNameComposer : public NameComposer
{ {
public: public:
virtual String MakeName(const String& shortName, const Object::Ptr& context) const; virtual String MakeName(const String& shortName, const Object::Ptr& context) const;
virtual Dictionary::Ptr ParseName(const String& name) const;
}; };
}}} }}}

View File

@ -31,6 +31,8 @@
#include "base/logger.hpp" #include "base/logger.hpp"
#include "base/exception.hpp" #include "base/exception.hpp"
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
using namespace icinga; using namespace icinga;
@ -57,6 +59,27 @@ String ScheduledDowntimeNameComposer::MakeName(const String& shortName, const Ob
return name; return name;
} }
Dictionary::Ptr ScheduledDowntimeNameComposer::ParseName(const String& name) const
{
std::vector<String> tokens;
boost::algorithm::split(tokens, name, boost::is_any_of("!"));
if (tokens.size() < 2)
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid ScheduledDowntime name."));
Dictionary::Ptr result = new Dictionary();
result->Set("host_name", tokens[0]);
if (tokens.size() > 2) {
result->Set("service_name", tokens[1]);
result->Set("name", tokens[2]);
} else {
result->Set("name", tokens[1]);
}
return result;
}
void ScheduledDowntime::StaticInitialize(void) void ScheduledDowntime::StaticInitialize(void)
{ {
l_Timer = new Timer(); l_Timer = new Timer();

View File

@ -29,6 +29,7 @@ class I2_ICINGA_API ScheduledDowntimeNameComposer : public NameComposer
{ {
public: public:
virtual String MakeName(const String& shortName, const Object::Ptr& context) const; virtual String MakeName(const String& shortName, const Object::Ptr& context) const;
virtual Dictionary::Ptr ParseName(const String& name) const;
}; };
}}} }}}

View File

@ -27,6 +27,8 @@
#include "base/utility.hpp" #include "base/utility.hpp"
#include <boost/foreach.hpp> #include <boost/foreach.hpp>
#include <boost/bind/apply.hpp> #include <boost/bind/apply.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
using namespace icinga; using namespace icinga;
@ -42,6 +44,21 @@ String ServiceNameComposer::MakeName(const String& shortName, const Object::Ptr&
return service->GetHostName() + "!" + shortName; return service->GetHostName() + "!" + shortName;
} }
Dictionary::Ptr ServiceNameComposer::ParseName(const String& name) const
{
std::vector<String> tokens;
boost::algorithm::split(tokens, name, boost::is_any_of("!"));
if (tokens.size() < 2)
BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid Service name."));
Dictionary::Ptr result = new Dictionary();
result->Set("host_name", tokens[0]);
result->Set("name", tokens[1]);
return result;
}
void Service::OnAllConfigLoaded(void) void Service::OnAllConfigLoaded(void)
{ {
Checkable::OnAllConfigLoaded(); Checkable::OnAllConfigLoaded();

View File

@ -32,6 +32,7 @@ class I2_ICINGA_API ServiceNameComposer : public NameComposer
{ {
public: public:
virtual String MakeName(const String& shortName, const Object::Ptr& context) const; virtual String MakeName(const String& shortName, const Object::Ptr& context) const;
virtual Dictionary::Ptr ParseName(const String& name) const;
}; };
}}} }}}

View File

@ -23,8 +23,8 @@ mkclass_target(zone.ti zone.tcpp zone.thpp)
set(remote_SOURCES set(remote_SOURCES
actionshandler.cpp apiaction.cpp actionshandler.cpp apiaction.cpp
apifunction.cpp apilistener.cpp apilistener.thpp apilistener-sync.cpp apifunction.cpp apilistener.cpp apilistener.thpp apilistener-sync.cpp
apiuser.cpp apiuser.thpp authority.cpp base64.cpp createobjecthandler.cpp configfileshandler.cpp apiuser.cpp apiuser.thpp authority.cpp base64.cpp createobjecthandler.cpp deleteobjecthandler.cpp
configmoduleshandler.cpp configmoduleutility.cpp configstageshandler.cpp configfileshandler.cpp configmoduleshandler.cpp configmoduleutility.cpp configstageshandler.cpp
endpoint.cpp endpoint.thpp filterutility.cpp endpoint.cpp endpoint.thpp filterutility.cpp
httpchunkedencoding.cpp httpconnection.cpp httphandler.cpp httprequest.cpp httpresponse.cpp httpchunkedencoding.cpp httpconnection.cpp httphandler.cpp httprequest.cpp httpresponse.cpp
httputility.cpp jsonrpc.cpp jsonrpcconnection.cpp jsonrpcconnection-heartbeat.cpp httputility.cpp jsonrpc.cpp jsonrpcconnection.cpp jsonrpcconnection-heartbeat.cpp

View File

@ -47,6 +47,14 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
String name = request.RequestUrl->GetPath()[2]; String name = request.RequestUrl->GetPath()[2];
NameComposer *nc = dynamic_cast<NameComposer *>(type.get());
Dictionary::Ptr nameParts;
if (nc) {
nameParts = nc->ParseName(name);
name = nameParts->Get("name");
}
Dictionary::Ptr params = HttpUtility::FetchRequestParameters(request); Dictionary::Ptr params = HttpUtility::FetchRequestParameters(request);
ConfigItemBuilder::Ptr builder = new ConfigItemBuilder(); ConfigItemBuilder::Ptr builder = new ConfigItemBuilder();
@ -64,6 +72,14 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
} }
} }
if (nameParts) {
ObjectLock olock(nameParts);
BOOST_FOREACH(const Dictionary::Pair& kv, nameParts) {
SetExpression *expr = new SetExpression(MakeIndexer(ScopeThis, kv.first), OpSetLiteral, MakeLiteral(kv.second));
builder->AddExpression(expr);
}
}
Dictionary::Ptr attrs = params->Get("attrs"); Dictionary::Ptr attrs = params->Get("attrs");
if (attrs) { if (attrs) {
@ -77,11 +93,28 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
ConfigItem::Ptr item = builder->Compile(); ConfigItem::Ptr item = builder->Compile();
item->Register(); item->Register();
ConfigItem::CommitAndActivate(); WorkQueue upq;
Dictionary::Ptr result1 = new Dictionary(); Dictionary::Ptr result1 = new Dictionary();
result1->Set("code", 200); int code;
result1->Set("status", "Object created."); String status;
if (!ConfigItem::CommitItems(upq) || !ConfigItem::ActivateItems(upq, false)) {
code = 500;
status = "Object could not be created.";
Array::Ptr errors = new Array();
BOOST_FOREACH(const boost::exception_ptr& ex, upq.GetExceptions()) {
errors->Add(DiagnosticInformation(ex));
}
result1->Set("errors", errors);
} else {
code = 200;
status = "Object created";
}
result1->Set("code", code);
result1->Set("status", status);
Array::Ptr results = new Array(); Array::Ptr results = new Array();
results->Add(result1); results->Add(result1);
@ -89,7 +122,7 @@ bool CreateObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
Dictionary::Ptr result = new Dictionary(); Dictionary::Ptr result = new Dictionary();
result->Set("results", results); result->Set("results", results);
response.SetStatus(200, "OK"); response.SetStatus(code, status);
HttpUtility::SendJsonBody(response, result); HttpUtility::SendJsonBody(response, result);
return true; return true;

View File

@ -0,0 +1,97 @@
/******************************************************************************
* 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/deleteobjecthandler.hpp"
#include "remote/httputility.hpp"
#include "remote/filterutility.hpp"
#include "remote/apiaction.hpp"
#include "config/configitem.hpp"
#include "base/exception.hpp"
#include "base/serializer.hpp"
#include <boost/algorithm/string.hpp>
#include <set>
using namespace icinga;
REGISTER_URLHANDLER("/v1", DeleteObjectHandler);
bool DeleteObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response)
{
if (request.RequestMethod != "DELETE")
return false;
if (request.RequestUrl->GetPath().size() < 2)
return false;
Type::Ptr type = FilterUtility::TypeFromPluralName(request.RequestUrl->GetPath()[1]);
if (!type)
return false;
QueryDescription qd;
qd.Types.insert(type);
Dictionary::Ptr params = HttpUtility::FetchRequestParameters(request);
params->Set("type", type->GetName());
if (request.RequestUrl->GetPath().size() >= 3) {
String attr = type->GetName();
boost::algorithm::to_lower(attr);
params->Set(attr, request.RequestUrl->GetPath()[2]);
}
std::vector<DynamicObject::Ptr> objs = FilterUtility::GetFilterTargets(qd, params);
Array::Ptr results = new Array();
BOOST_FOREACH(const DynamicObject::Ptr& obj, objs) {
Dictionary::Ptr result1 = new Dictionary();
result1->Set("type", type->GetName());
result1->Set("name", obj->GetName());
ConfigItem::Ptr item = ConfigItem::GetObject(type->GetName(), obj->GetName());
try {
obj->Deactivate();
if (item)
item->Unregister();
else
obj->Unregister();
result1->Set("code", 200);
result1->Set("status", "Object was deleted.");
} catch (const std::exception& ex) {
result1->Set("code", 500);
result1->Set("status", "Object could not be deleted: " + DiagnosticInformation(ex));
}
results->Add(result1);
}
Dictionary::Ptr result = new Dictionary();
result->Set("results", results);
response.SetStatus(200, "OK");
HttpUtility::SendJsonBody(response, result);
return true;
}

View File

@ -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 DELETEOBJECTHANDLER_H
#define DELETEOBJECTHANDLER_H
#include "remote/httphandler.hpp"
namespace icinga
{
class I2_REMOTE_API DeleteObjectHandler : public HttpHandler
{
public:
DECLARE_PTR_TYPEDEFS(DeleteObjectHandler);
virtual bool HandleRequest(const ApiUser::Ptr& user, HttpRequest& request, HttpResponse& response);
};
}
#endif /* DELETEOBJECTHANDLER_H */

View File

@ -38,7 +38,7 @@ Type::Ptr FilterUtility::TypeFromPluralName(const String& pluralName)
Type::Ptr type = Type::GetByName(dtype->GetName()); Type::Ptr type = Type::GetByName(dtype->GetName());
ASSERT(type); ASSERT(type);
String pname = GetPluralName(type); String pname = type->GetPluralName();
boost::algorithm::to_lower(pname); boost::algorithm::to_lower(pname);
if (uname == pname) if (uname == pname)
@ -48,16 +48,6 @@ Type::Ptr FilterUtility::TypeFromPluralName(const String& pluralName)
return Type::Ptr(); return Type::Ptr();
} }
String FilterUtility::GetPluralName(const Type::Ptr& type)
{
String name = type->GetName();
if (name[name.GetLength() - 1] == 'y')
return name.SubStr(0, name.GetLength() - 1) + "ies";
else
return name + "s";
}
DynamicObject::Ptr FilterUtility::GetObjectByTypeAndName(const String& type, const String& name) DynamicObject::Ptr FilterUtility::GetObjectByTypeAndName(const String& type, const String& name)
{ {
DynamicType::Ptr dtype = DynamicType::GetByName(type); DynamicType::Ptr dtype = DynamicType::GetByName(type);
@ -82,7 +72,7 @@ std::vector<DynamicObject::Ptr> FilterUtility::GetFilterTargets(const QueryDescr
result.push_back(obj); result.push_back(obj);
} }
attr = GetPluralName(type); attr = type->GetPluralName();
boost::algorithm::to_lower(attr); boost::algorithm::to_lower(attr);
if (query->Contains(attr)) { if (query->Contains(attr)) {

View File

@ -41,7 +41,6 @@ struct QueryDescription
class I2_REMOTE_API FilterUtility class I2_REMOTE_API FilterUtility
{ {
public: public:
static String GetPluralName(const Type::Ptr& type);
static Type::Ptr TypeFromPluralName(const String& pluralName); static Type::Ptr TypeFromPluralName(const String& pluralName);
static DynamicObject::Ptr GetObjectByTypeAndName(const String& type, const String& name); static DynamicObject::Ptr GetObjectByTypeAndName(const String& type, const String& name);
static std::vector<DynamicObject::Ptr> GetFilterTargets(const QueryDescription& qd, const Dictionary::Ptr& query); static std::vector<DynamicObject::Ptr> GetFilterTargets(const QueryDescription& qd, const Dictionary::Ptr& query);

View File

@ -65,7 +65,7 @@ bool ModifyObjectHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& r
BOOST_FOREACH(const DynamicObject::Ptr& obj, objs) { BOOST_FOREACH(const DynamicObject::Ptr& obj, objs) {
Dictionary::Ptr result1 = new Dictionary(); Dictionary::Ptr result1 = new Dictionary();
result1->Set("type", obj->GetReflectionType()->GetName()); result1->Set("type", type->GetName());
result1->Set("name", obj->GetName()); result1->Set("name", obj->GetName());
String key; String key;

View File

@ -87,7 +87,8 @@ struct GlobalConfigFixture {
DaemonUtility::LoadConfigFiles(configs, "icinga2.debug", "icinga2.vars"); DaemonUtility::LoadConfigFiles(configs, "icinga2.debug", "icinga2.vars");
/* ignore config errors */ /* ignore config errors */
ConfigItem::ActivateItems(); WorkQueue upq;
ConfigItem::ActivateItems(upq, false);
} }
~GlobalConfigFixture() ~GlobalConfigFixture()