This file is indexed.

/usr/share/check_mk/web/plugins/sidebar/wato.py is in check-mk-multisite 1.2.8p16-1ubuntu0.1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
#!/usr/bin/python
# -*- encoding: utf-8; py-indent-offset: 4 -*-
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# | Copyright Mathias Kettner 2014             mk@mathias-kettner.de |
# +------------------------------------------------------------------+
#
# This file is part of Check_MK.
# The official homepage is at http://mathias-kettner.de/check_mk.
#
# check_mk 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 in version 2.  check_mk is  distributed
# in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with-
# out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A
# PARTICULAR PURPOSE. See the  GNU General Public License for more de-
# tails. You should have  received  a copy of the  GNU  General Public
# License along with GNU Make; see the file  COPYING.  If  not,  write
# to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor,
# Boston, MA 02110-1301 USA.

import config, wato, views, dashboard

#   +----------------------------------------------------------------------+
#   |                     __        ___  _____ ___                         |
#   |                     \ \      / / \|_   _/ _ \                        |
#   |                      \ \ /\ / / _ \ | || | | |                       |
#   |                       \ V  V / ___ \| || |_| |                       |
#   |                        \_/\_/_/   \_\_| \___/                        |
#   |                                                                      |
#   +----------------------------------------------------------------------+
def render_wato(mini):
    if not config.wato_enabled:
        html.write(_("WATO is disabled."))
        return False
    elif not config.may("wato.use"):
        html.write(_("You are not allowed to use Check_MK's web configuration GUI."))
        return False

    if mini:
        html.icon_button("wato.py", _("Main Menu"), "home", target="main")
    else:
        iconlink(_("Main Menu"), "wato.py", "home")
    for mode, title, icon, permission, help in wato.modules:
        if permission and "." not in permission:
            permission = "wato." + permission
        if not permission or config.may(permission) or config.may("wato.seeall"):
            url = "wato.py?mode=%s" % mode
            if mini:
                html.icon_button(url, title, icon, target="main")
            else:
                iconlink(title, url, icon)

    num_pending = wato.num_pending_changes()
    if num_pending:
        footnotelinks([(_("%d changes") % num_pending, "wato.py?mode=changelog")])
        html.write('<div class=clear></div>')


sidebar_snapins["admin"] = {
    "title" : _("WATO &middot; Configuration"),
    "description" : _("Direct access to WATO - the web administration GUI of Check_MK"),
    "render" : lambda: render_wato(False),
    "refresh" : 60, # refresh pending changes, if other user modifies something
    "allowed" : [ "admin", "user" ],
}

sidebar_snapins["admin_mini"] = {
    "title" : _("WATO &middot; Quickaccess"),
    "description" : _("Access to WATO modules with only icons (saves space)"),
    "render" : lambda: render_wato(True),
    "refresh" : 60, # refresh pending changes, if other user modifies something
    "allowed" : [ "admin", "user" ],
    "styles": """
#snapin_admin_mini {
    padding-top: 6px;
    clear: right;
}
#snapin_admin_mini img {
    margin-right: 3.9px;
    margin-bottom: 4px;
    width: 18px;
    height: 18px;
    position: relative;
    left: 3px;
    padding: 0;
}

#snapin_admin_mini div.footnotelink {
    float: right;
}
#snapin_admin_mini div.clear {
    clear: right;
}
""",
}

#   .----------------------------------------------------------------------.
#   |            _____     _     _           _                             |
#   |           |  ___|__ | | __| | ___ _ __| |_ _ __ ___  ___             |
#   |           | |_ / _ \| |/ _` |/ _ \ '__| __| '__/ _ \/ _ \            |
#   |           |  _| (_) | | (_| |  __/ |  | |_| | |  __/  __/            |
#   |           |_|  \___/|_|\__,_|\___|_|   \__|_|  \___|\___|            |
#   |                                                                      |
#   +----------------------------------------------------------------------+
#   |                                                                      |
#   '----------------------------------------------------------------------'

def compute_foldertree():
    html.live.set_prepend_site(True)
    query = "GET hosts\n" \
            "Stats: state >= 0\n" \
            "Columns: filename"
    hosts = html.live.query(query)
    html.live.set_prepend_site(False)
    hosts.sort()

    def get_folder(path, num = 0):
        folder = wato.Folder.folder(path)
        return {
            'title':      folder.title() or path.split('/')[-1],
            '.path':      path,
            '.num_hosts': num,
            '.folders':   {},
        }


    # After the query we have a list of lists where each
    # row is a folder with the number of hosts on this level.
    #
    # Now get number of hosts by folder
    # Count all childs for each folder
    user_folders = {}
    for site, filename, num in hosts:
        # Remove leading /wato/
        wato_folder_path = filename[6:]

        # Loop through all levels of this folder to add the
        # host count to all parent levels
        path_parts = wato_folder_path.split('/')
        for num_parts in range(0, len(path_parts)):
            this_folder_path = '/'.join(path_parts[:num_parts])

            if wato.Folder.folder_exists(this_folder_path):
                if this_folder_path not in user_folders:
                    user_folders[this_folder_path] = get_folder(this_folder_path, num)
                else:
                    user_folders[this_folder_path]['.num_hosts'] += num

    #
    # Now build the folder tree
    #
    for folder_path, folder in sorted(user_folders.items(), reverse = True):
        if not folder_path:
            continue
        folder_parts = folder_path.split('/')
        parent_folder = '/'.join(folder_parts[:-1])

        user_folders[parent_folder]['.folders'][folder_path] = folder
        del user_folders[folder_path]

    #
    # Now reduce the tree by e.g. removing top-level parts which the user is not
    # permitted to see directly. Example:
    # Locations
    #  -> Hamburg: Permitted to see all hosts
    #  -> Munich:  Permitted to see no host
    # In this case, where only a single child with hosts is available, remove the
    # top level
    def reduce_tree(folders):
        for folder_path, folder in folders.items():
            if len(folder['.folders']) == 1 and folder['.num_hosts'] == 0:
                child_path, child_folder = folder['.folders'].items()[0]
                folders[child_path] = child_folder
                del folders[folder_path]

                reduce_tree(folders)

    reduce_tree(user_folders)
    return user_folders


# Note: the dictionary that represents the folder here is *not*
# the datastructure from WATO but a result of compute_foldertree(). The reason:
# We fetch the information via livestatus - not from WATO.
def render_tree_folder(tree_id, folder, js_func):
    subfolders = folder.get(".folders", {}).values()
    subfolders.sort(cmp = lambda f1, f2: cmp(f1["title"].lower(), f2["title"].lower()))

    is_leaf = len(subfolders) == 0

    # Suppress indentation for non-emtpy root folder
    if folder['.path'] == '' and is_leaf:
        html.write("<ul>") # empty root folder
    elif folder and folder['.path'] != '':
        html.write("<ul style='padding-left: 0px;'>")

    title = '<a class="link" href="#" onclick="%s(this, \'%s\');">%s (%d)</a>' % (
            js_func, folder[".path"], html.attrencode(folder["title"]), folder[".num_hosts"])

    if not is_leaf:
        html.begin_foldable_container(tree_id, "/" + folder[".path"], False, HTML(title))
        for subfolder in subfolders:
            render_tree_folder(tree_id, subfolder, js_func)
        html.end_foldable_container()
    else:
        html.write("<li>" + title + "</li>")

    html.write("</ul>")


def sort_by_title(folders):
    def folder_cmp(f1, f2):
        return cmp(f1["title"].lower(), f2["title"].lower())
    folders.sort(cmp = folder_cmp)
    return folders



def render_wato_foldertree():
    if not wato.is_wato_slave_site():
        if not config.wato_enabled:
            html.write(_("WATO is disabled."))
            return False

    user_folders = compute_foldertree()

    #
    # Render link target selection
    #
    selected_topic, selected_target = config.load_user_file("foldertree", (_('Hosts'), 'allhosts'))

    views.load_views()
    dashboard.load_dashboards()
    topic_views  = visuals_by_topic(views.permitted_views().items() + dashboard.permitted_dashboards().items())
    topics = [ (t, t) for t, s in topic_views ]
    html.select("topic", topics, selected_topic, onchange = 'wato_tree_topic_changed(this)')
    html.write('<span class=left>%s</span>' % _('Topic:'))

    for topic, view_list in topic_views:
        targets = []
        for t, title, name, is_view in view_list:
            if config.visible_views and name not in config.visible_views:
                continue
            if config.hidden_views and name in config.hidden_views:
                continue
            if t == topic:
                if not is_view:
                    name = 'dashboard|' + name
                targets.append((name, title))

        attrs = {}
        if topic != selected_topic:
            attrs['style'] = 'display:none'
            default = ''
        else:
            default = selected_target

        html.select("target_%s" % topic, targets, default, attrs = attrs, onchange = 'wato_tree_target_changed(this)')

    html.write('<span class=left>%s</span>' % _('View:'))

    # Now render the whole tree
    if user_folders:
        render_tree_folder("wato-hosts", user_folders.values()[0], 'wato_tree_click')


sidebar_snapins['wato_foldertree'] = {
    'title'       : _('Tree of folders'),
    'description' : _('This snapin shows the folders defined in WATO. It can be used to '
                       'open views filtered by the WATO folder. It works standalone, without '
                       'interaction with any other snapin.'),
    'render'      : render_wato_foldertree,
    'allowed'     : [ 'admin', 'user', 'guest' ],
    'styles'      : """
#snapin_wato_foldertree select {
    float: right;
    padding: 0;
    width:   190px;
    height: 19px;
    margin-bottom: 2px;
    background-color: #6da1b8;
    color: #fff;
    border-color: #123a4a;
    font-size: 8pt;
}
#snapin_wato_foldertree select option {
    background-color: #6da1b8;
}
#snapin_wato_foldertree span {
    margin-top: 1px;
    display: block;
    color:  #ffffff;
    height: 20px;
}
"""
}

def render_wato_folders():
    user_folders = compute_foldertree()

    if user_folders:
        render_tree_folder("wato-folders", user_folders.values()[0], 'wato_folders_clicked')

sidebar_snapins['wato_folders'] = {
    'title'       : _('Folders'),
    'description' : _('This snapin shows the folders defined in WATO. It can '
                      'be used to open views filtered by the WATO folder. This '
                      'snapin interacts with the "Views" snapin, when both are '
                      'enabled.'),
    'render'      : render_wato_folders,
    'allowed'     : [ 'admin', 'user', 'guest' ],
}