Module: check_mk
Branch: master
Commit: 018961ddfb14ef8375905a8c8a176b012deb8884
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=018961ddfb14ef…
Author: Andreas Boesl <ab(a)mathias-kettner.de>
Date: Thu Nov 2 14:05:37 2017 +0100
5238 FIX WATO users now only see their configured sites in the Site-DropdownChoice
A user can be configured only to see/configure a subset of the available sites.
The site dropdown choice, however, always showed all available sites. This has been fixed.
Change-Id: I79c45746211df5c911b96604680631d8de342306
---
.werks/5238 | 12 ++++++++++++
web/htdocs/valuespec.py | 29 ++++++++++++++++++++++++-----
web/plugins/wato/builtin_attributes.py | 1 -
3 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/.werks/5238 b/.werks/5238
new file mode 100644
index 0000000..43661bb
--- /dev/null
+++ b/.werks/5238
@@ -0,0 +1,12 @@
+Title: WATO users now only see their configured sites in the Site-DropdownChoice
+Level: 1
+Component: wato
+Compatible: compat
+Edition: cre
+Version: 1.5.0i1
+Date: 1509627717
+Class: fix
+
+A user can be configured only to see/configure a subset of the available sites.
+The site dropdown choice, however, always showed all available sites. This has been fixed.
+
diff --git a/web/htdocs/valuespec.py b/web/htdocs/valuespec.py
index b29f9df..ee74dea 100644
--- a/web/htdocs/valuespec.py
+++ b/web/htdocs/valuespec.py
@@ -34,7 +34,7 @@
# -> rename to Boolean
# -> Add alternative rendering "dropdown"
-import math, os, time, re, sre_constants, urlparse, forms, tempfile
+import math, os, time, re, sre_constants, urlparse, forms, tempfile, types
import base64
import hashlib
import socket
@@ -99,7 +99,7 @@ class ValueSpec(object):
# for same cases where the default value is known.
def default_value(self):
try:
- if type(self._default_value) == type(lambda:True):
+ if type(self._default_value) in [types.FunctionType, types.MethodType]:
return self._default_value()
else:
return self._default_value
@@ -4583,14 +4583,13 @@ def ListOfCAs(**args):
class SiteChoice(DropdownChoice):
def __init__(self, **kwargs):
- import config
kwargs.setdefault("title", _("Site"))
kwargs.setdefault("help", _("Specify the site of your choice"))
- kwargs.setdefault("default_value", config.default_site())
+ kwargs.setdefault("default_value", self._site_default_value)
kwargs.setdefault("invalid_choice_error", _("The configured site is not known to this site."))
kwargs.update({
- "choices": config.site_choices,
+ "choices": self._site_choices,
"invalid_choice": "complain",
"invalid_choice_title": _("Unknown site (%s)"),
})
@@ -4598,6 +4597,26 @@ class SiteChoice(DropdownChoice):
super(SiteChoice, self).__init__(**kwargs)
+ def _site_default_value(self):
+ import watolib
+ if watolib.is_wato_slave_site():
+ return False
+
+ import config
+ default_site = config.default_site()
+ authorized_site_ids = map(lambda x: x[0], config.user.authorized_sites(unfiltered_sites=config.configured_sites()))
+ if default_site and default_site in authorized_site_ids:
+ return default_site
+ raise
+
+
+ def _site_choices(self):
+ import config
+ authorized_site_ids = map(lambda x: x[0], config.user.authorized_sites(unfiltered_sites=config.configured_sites()))
+ return config.site_choices(filter_func=lambda site_id, site: site_id in authorized_site_ids)
+
+
+
class TimeperiodSelection(ElementSelection):
def __init__(self, **kwargs):
diff --git a/web/plugins/wato/builtin_attributes.py b/web/plugins/wato/builtin_attributes.py
index 03d91a5..adf2eeb 100644
--- a/web/plugins/wato/builtin_attributes.py
+++ b/web/plugins/wato/builtin_attributes.py
@@ -490,7 +490,6 @@ class SiteAttribute(ValueSpecAttribute):
ValueSpecAttribute.__init__(self, "site", SiteChoice(
title=_("Monitored on site"),
help=_("Specify the site that should monitor this host."),
- default_value = default_site,
invalid_choice_error = _("The configured site is not known to this site. In case you "
"are configuring in a distributed slave, this may be a host "
"monitored by another site. If you want to modify this "
Module: check_mk
Branch: master
Commit: 33281d4ab0f81e1850669c0d9624aefcd610f3ba
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=33281d4ab0f81e…
Author: Jukka Aro <ja(a)mathias-kettner.de>
Date: Mon Oct 30 16:20:38 2017 +0100
5409 FIX Windows eventlog: wrong last state saved
The initial run of Windows agent after fresh installation caused an
incorrect last state to be written in the state file eventstate.txt.
As a result, no new entries were read from the eventlog. Broken since
commit 9619c43a171b7e9258f012f547c1d186660c6268.
Change-Id: I47378f667b7ecf8c481f7ed9c7105623b4051a2b
---
.werks/5409 | 16 ++++++++++++++++
agents/windows/EventLog.cc | 24 ++++++++++++++++++------
agents/windows/EventLog.h | 7 ++++++-
agents/windows/EventLogVista.cc | 23 ++++++++++++++++++++---
agents/windows/EventLogVista.h | 4 +++-
agents/windows/IEventLog.h | 19 ++++++++++++++-----
agents/windows/build_version | 2 +-
agents/windows/sections/SectionEventlog.cc | 10 ++++++++--
8 files changed, 86 insertions(+), 19 deletions(-)
diff --git a/.werks/5409 b/.werks/5409
new file mode 100644
index 0000000..39cdf54
--- /dev/null
+++ b/.werks/5409
@@ -0,0 +1,16 @@
+Title: Windows eventlog: wrong last state saved
+Level: 1
+Component: checks
+Class: fix
+Compatible: compat
+Edition: cre
+State: unknown
+Version: 1.5.0i1
+Date: 1509376514
+
+The initial run of Windows agent after fresh installation caused an
+incorrect last state to be written in the state file eventstate.txt.
+As a result, no new entries were read from the eventlog. Broken since
+commit 91797ac9f7d69fc94119c08ea0df4baccaea2b6.
+
+
diff --git a/agents/windows/EventLog.cc b/agents/windows/EventLog.cc
index a840d24..8fb0d50 100644
--- a/agents/windows/EventLog.cc
+++ b/agents/windows/EventLog.cc
@@ -297,23 +297,23 @@ void EventLog::reset() {
wstring EventLog::getName() const { return _name; }
-uint64_t EventLog::seek(uint64_t record_number) {
+void EventLog::seek(uint64_t record_number) {
DWORD oldest_record, record_count;
if (_log.GetOldestEventLogRecord(&oldest_record) &&
(record_number < oldest_record)) {
- // can't seek to older record
+ // Beyond the oldest record:
_record_offset = oldest_record;
} else if (_log.GetNumberOfEventLogRecords(&record_count) &&
- (record_number > oldest_record + record_count)) {
+ (record_number >= oldest_record + record_count)) {
+ // Beyond the newest record. Note: set offset intentionally to the next
+ // record after the currently last one!
_record_offset = oldest_record + record_count;
} else {
- // not actually seeking but storing for the next actual read
+ // Within bounds, the offset for the next actual read:
_record_offset = record_number;
}
_buffer_offset = _buffer_used; // enforce that a new chunk is fetched
-
- return _record_offset;
}
std::unique_ptr<IEventLogRecord> EventLog::read() {
@@ -351,6 +351,18 @@ std::unique_ptr<IEventLogRecord> EventLog::read() {
}
}
+uint64_t EventLog::getLastRecordId() {
+ DWORD oldestRecord = 0;
+ DWORD recordCount = 0;
+ if (_log.GetOldestEventLogRecord(&oldestRecord) &&
+ _log.GetNumberOfEventLogRecords(&recordCount) &&
+ oldestRecord + recordCount > 0) {
+ return oldestRecord + recordCount - 1;
+ } else {
+ return 0;
+ }
+}
+
bool EventLog::fillBuffer() {
_buffer_offset = 0;
diff --git a/agents/windows/EventLog.h b/agents/windows/EventLog.h
index eb063fc..cab226b 100644
--- a/agents/windows/EventLog.h
+++ b/agents/windows/EventLog.h
@@ -149,7 +149,7 @@ public:
* In this case this function will still work as expected but the next read
* will be slow.
*/
- virtual uint64_t seek(uint64_t record_id) override;
+ virtual void seek(uint64_t record_id) override;
/**
* read the next eventlog record
@@ -160,6 +160,11 @@ public:
virtual std::unique_ptr<IEventLogRecord> read() override;
/**
+ * return the ID of the last record in eventlog
+ */
+ virtual uint64_t getLastRecordId() override;
+
+ /**
* get a list of dlls that contain eventid->message mappings for this
* eventlog and the specified source
*/
diff --git a/agents/windows/EventLogVista.cc b/agents/windows/EventLogVista.cc
index 1b73e1a..b93bada 100644
--- a/agents/windows/EventLogVista.cc
+++ b/agents/windows/EventLogVista.cc
@@ -338,7 +338,7 @@ std::wstring EventLogVista::renderBookmark(EVT_HANDLE bookmark) const {
return buffer;
}
-uint64_t EventLogVista::seek(uint64_t record_id) {
+void EventLogVista::seek(uint64_t record_id) {
{
// The api to retrieve the oldest event log id is bugged. bloody hell...
// to get the right offset if record_id is beyond the valid range, we
@@ -410,8 +410,6 @@ uint64_t EventLogVista::seek(uint64_t record_id) {
throw win_exception(
_winapi, std::string("failed to subscribe to ") + to_utf8(_path));
}
-
- return record_id;
}
std::unique_ptr<IEventLogRecord> EventLogVista::read() {
@@ -425,6 +423,25 @@ std::unique_ptr<IEventLogRecord> EventLogVista::read() {
_winapi);
}
+uint64_t EventLogVista::getLastRecordId() {
+ auto log = std::make_unique<EventLogWrapper>(
+ *_evt, EvtQueryReverseDirection, _path, _winapi);
+
+ EVT_HANDLE event_handle = nullptr;
+ DWORD num_events = 0;
+ if (evt().next &&
+ evt().next(log->get_handle(), 1, &event_handle, INFINITE, 0,
+ &num_events)) {
+ auto event = std::make_unique<ManagedEventHandle>(*_evt, event_handle);
+
+ return EventLogRecordVista(event->get_handle(), _evt.get(),
+ _render_context->get_handle(), _winapi)
+ .recordId();
+ } else {
+ return 0;
+ }
+}
+
bool EventLogVista::fillBuffer() {
// this ensures all previous event handles are closed and nulled
reset();
diff --git a/agents/windows/EventLogVista.h b/agents/windows/EventLogVista.h
index de9195f..bbea22f 100644
--- a/agents/windows/EventLogVista.h
+++ b/agents/windows/EventLogVista.h
@@ -150,10 +150,12 @@ public:
virtual void reset() override;
- virtual uint64_t seek(uint64_t record_id) override;
+ virtual void seek(uint64_t record_id) override;
virtual std::unique_ptr<IEventLogRecord> read() override;
+ virtual uint64_t getLastRecordId() override;
+
private:
static const int EVENT_BLOCK_SIZE = 16;
diff --git a/agents/windows/IEventLog.h b/agents/windows/IEventLog.h
index 10d7df0..ebeb25c 100644
--- a/agents/windows/IEventLog.h
+++ b/agents/windows/IEventLog.h
@@ -70,13 +70,17 @@ public:
* seek to the specified record on the next read or, if the record_number is
* older than the oldest existing record, seek to the beginning. If the
* record_number is the highest representable uint32_t, seek to the end of
- * the log such that only future events are retrieveda
+ * the log such that only future events are retrieved
*
- * returns the actual record_id we seeked to, which may differ from the
- * input
- * if it was outside the available range
+ * WARNING:
+ * The implementations for pre-Vista and post-Vista are completely
+ * different.
+ * We *must not* return any value as it is different between pre/post Vista.
+ * For obtaining the ID of the last record in eventlog, please use
+ * getLastRecordId instead. It has own implementations for pre/post Vista
+ * but return a uniformly correct value.
*/
- virtual uint64_t seek(uint64_t record_id) = 0;
+ virtual void seek(uint64_t record_id) = 0;
/**
* read the next eventlog record
@@ -87,6 +91,11 @@ public:
virtual std::unique_ptr<IEventLogRecord> read() = 0;
/**
+ * return the ID of the last record in eventlog
+ */
+ virtual uint64_t getLastRecordId() = 0;
+
+ /**
* get a list of dlls that contain eventid->message mappings for this
* eventlog and the specified source
*/
diff --git a/agents/windows/build_version b/agents/windows/build_version
index ce89b3e..47efd9a 100644
--- a/agents/windows/build_version
+++ b/agents/windows/build_version
@@ -1 +1 @@
-2992
+2994
diff --git a/agents/windows/sections/SectionEventlog.cc b/agents/windows/sections/SectionEventlog.cc
index 9e6f79d..773e3d4 100644
--- a/agents/windows/sections/SectionEventlog.cc
+++ b/agents/windows/sections/SectionEventlog.cc
@@ -166,6 +166,9 @@ std::pair<uint64_t, int> processEventLog(
previouslyReadId + (uint64limits::max() == previouslyReadId ? 0 : 1);
int worstState = 0;
uint64_t lastRecordId = previouslyReadId;
+ // WARNING:
+ // seek implementations for pre-Vista and post-Vista are completely different.
+ // seek *must not* return any value as it is different between pre/post Vista.
log.seek(seekPosition);
while (auto record = std::move(log.read())) {
lastRecordId = record->recordId();
@@ -210,8 +213,11 @@ uint64_t SectionEventlog::outputEventlog(std::ostream &out, const char *logname,
};
processEventLog(*log, previouslyReadId, level, outputRecord);
}
-
- return lastReadId;
+ // Return the last entry number. We need to fetch the last record ID
+ // separately if INT_MAX was used as seek offset and no new entries
+ // were read.
+ return (std::numeric_limits<uint64_t>::max() == lastReadId) ?
+ log->getLastRecordId() : lastReadId;
}
} catch (const std::exception &e) {
Error(_logger) << "failed to read event log: " << e.what() << std::endl;
Module: check_mk
Branch: master
Commit: f7f576c7f1e3c3e0ba53e358ef96263b91d97628
URL: http://git.mathias-kettner.de/git/?p=check_mk.git;a=commit;h=f7f576c7f1e3c3…
Author: Lars Michelsen <lm(a)mathias-kettner.de>
Date: Thu Nov 2 11:33:22 2017 +0100
5429 FIX Fixed broken event history expiration (when using default settings)
The Event Console was not deleting outdated entries from the event history.
With the default settings it is intended to delete entries older than 365
days from the EC archive. This did not work.
A message like this can be found each "Housekeeping interval", normaly 1 minute:
[1509618281.352829] Error expiring log files: year out of range
This time window can be configured with the setting "Event history lifetime".
As a workaround you can simply open this setting and save it with the default
value. This will make the event deletion work as expected.
When you are affected, this may result in a way too huge Event Console archive
directory (<tt>~/var/mkeventd/history</tt>) which may result in slow
"Event Console History" views (depends on your filtering). You could clean up
the archive directory by hand to improve the situation.
After applying the update, the next housekeeping run will clean up all your old
archived events.
Change-Id: Ie00346286eee239377b2c38c2e2c05b757084e7a
---
.werks/5429 | 29 +++++++++++++++++++++++++++++
bin/mkeventd | 23 +++++++++++++++++------
lib/event_console.py | 2 +-
3 files changed, 47 insertions(+), 7 deletions(-)
diff --git a/.werks/5429 b/.werks/5429
new file mode 100644
index 0000000..abf304a
--- /dev/null
+++ b/.werks/5429
@@ -0,0 +1,29 @@
+Title: Fixed broken event history expiration (when using default settings)
+Level: 2
+Component: ec
+Class: fix
+Compatible: compat
+Edition: cre
+State: unknown
+Version: 1.5.0i1
+Date: 1509618033
+
+The Event Console was not deleting outdated entries from the event history.
+With the default settings it is intended to delete entries older than 365
+days from the EC archive. This did not work.
+
+A message like this can be found each "Housekeeping interval", normaly 1 minute:
+
+[1509618281.352829] Error expiring log files: year out of range
+
+This time window can be configured with the setting "Event history lifetime".
+As a workaround you can simply open this setting and save it with the default
+value. This will make the event deletion work as expected.
+
+When you are affected, this may result in a way too huge Event Console archive
+directory (<tt>~/var/mkeventd/history</tt>) which may result in slow
+"Event Console History" views (depends on your filtering). You could clean up
+the archive directory by hand to improve the situation.
+
+After applying the update, the next housekeeping run will clean up all your old
+archived events.
diff --git a/bin/mkeventd b/bin/mkeventd
index 4071499..c384398 100755
--- a/bin/mkeventd
+++ b/bin/mkeventd
@@ -55,6 +55,7 @@ import cmk.paths
import cmk.defines as defines
import cmk.daemon
import cmk.event_console
+import cmk.render
import cmk.profile
from cmk.regex import regex, is_regex
@@ -744,7 +745,7 @@ def update_mongodb_history_lifetime():
if not g_mongo_conn:
connect_mongodb()
- if get_mongodb_max_history_age() == g_config['history_lifetime']:
+ if get_mongodb_max_history_age() == g_config['history_lifetime'] * 86400:
return # do not update already correct index
try:
@@ -754,7 +755,7 @@ def update_mongodb_history_lifetime():
# Delete messages after x days
g_mongo_db.ec_archive.ensure_index([('dt', DESCENDING)],
- expireAfterSeconds = g_config['history_lifetime'],
+ expireAfterSeconds = g_config['history_lifetime'] * 86400,
unique = False
)
@@ -970,16 +971,26 @@ def expire_logfiles(flush = False):
try:
now = time.time()
min_mtime = now - g_config["history_lifetime"] * 86400
+
+ logger.verbose("Expiring logfiles (Horizon: %d days -> %s)" %
+ (g_config["history_lifetime"], cmk.render.date_and_time(min_mtime)))
+
for fn in os.listdir(log_dir):
if fn.endswith(".log"):
path = log_dir + "/" + fn
+
if flush:
logger.info("Flushed log file %s" % path)
os.remove(path)
- elif os.stat(path).st_mtime < min_mtime:
- logger.info("Deleting log file %s (lifetime expired after %d days)" %
- (path, g_config["history_lifetime"]))
- os.remove(path)
+
+ else:
+ file_mtime = os.stat(path).st_mtime
+
+ if file_mtime < min_mtime:
+ logger.info("Deleting log file %s (age %s)" %
+ (path, cmk.render.date_and_time(file_mtime)))
+ os.remove(path)
+
except Exception as e:
if opt_debug:
raise
diff --git a/lib/event_console.py b/lib/event_console.py
index d8fd006..eefe2a7 100644
--- a/lib/event_console.py
+++ b/lib/event_console.py
@@ -48,7 +48,7 @@ def default_config():
"retention_interval": 60,
"housekeeping_interval": 60,
"statistics_interval": 5,
- "history_lifetime": 365 * 24 * 3600,
+ "history_lifetime": 365, # days
"history_rotation": "daily",
"replication": None,
"remote_status": None,