1
|
|
|
# -*- coding: utf-8 -*- |
2
|
|
|
# |
3
|
|
|
# This file is part of Glances. |
4
|
|
|
# |
5
|
|
|
# Copyright (C) 2021 Nicolargo <[email protected]> |
6
|
|
|
# |
7
|
|
|
# Glances is free software; you can redistribute it and/or modify |
8
|
|
|
# it under the terms of the GNU Lesser General Public License as published by |
9
|
|
|
# the Free Software Foundation, either version 3 of the License, or |
10
|
|
|
# (at your option) any later version. |
11
|
|
|
# |
12
|
|
|
# Glances is distributed in the hope that it will be useful, |
13
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
14
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15
|
|
|
# GNU Lesser General Public License for more details. |
16
|
|
|
# |
17
|
|
|
# You should have received a copy of the GNU Lesser General Public License |
18
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. |
19
|
|
|
|
20
|
|
|
"""Fields description interface class.""" |
21
|
|
|
|
22
|
|
|
from pprint import pformat |
23
|
|
|
import json |
24
|
|
|
import time |
25
|
|
|
|
26
|
|
|
from glances.logger import logger |
27
|
|
|
from glances.compat import iteritems |
28
|
|
|
|
29
|
|
|
API_URL = "http://localhost:61208/api/3" |
30
|
|
|
|
31
|
|
|
APIDOC_HEADER = """\ |
32
|
|
|
.. _api: |
33
|
|
|
|
34
|
|
|
API (Restfull/JSON) documentation |
35
|
|
|
================================= |
36
|
|
|
|
37
|
|
|
The Glances Restfull/API server could be ran using the following command line: |
38
|
|
|
|
39
|
|
|
.. code-block:: bash |
40
|
|
|
|
41
|
|
|
# glances -w --disable-webui |
42
|
|
|
|
43
|
|
|
Note: Change request URL api/3 by api/2 if you use Glances 2.x. |
44
|
|
|
""" |
45
|
|
|
|
46
|
|
|
|
47
|
|
|
def indent_stat(stat, indent=' '): |
48
|
|
|
# Indent stats to pretty print it |
49
|
|
|
if isinstance(stat, list) and len(stat) > 1 and isinstance(stat[0], dict): |
50
|
|
|
# Only display two first items |
51
|
|
|
return indent + pformat(stat[0:2]).replace('\n', '\n' + indent) |
52
|
|
|
else: |
53
|
|
|
return indent + pformat(stat).replace('\n', '\n' + indent) |
54
|
|
|
|
55
|
|
|
|
56
|
|
|
def print_plugins_list(stat): |
57
|
|
|
sub_title = 'GET plugins list' |
58
|
|
|
print(sub_title) |
59
|
|
|
print('-' * len(sub_title)) |
60
|
|
|
print('') |
61
|
|
|
print('Get the plugins list::') |
62
|
|
|
print('') |
63
|
|
|
print(' # curl {}/pluginslist'.format(API_URL)) |
64
|
|
|
print(indent_stat(stat)) |
65
|
|
|
print('') |
66
|
|
|
|
67
|
|
|
|
68
|
|
|
def print_plugin_export(plugin, stat_export): |
69
|
|
|
sub_title = 'GET {}'.format(plugin) |
70
|
|
|
print(sub_title) |
71
|
|
|
print('-' * len(sub_title)) |
72
|
|
|
print('') |
73
|
|
|
|
74
|
|
|
print('Get plugin stats::') |
75
|
|
|
print('') |
76
|
|
|
print(' # curl {}/{}'.format(API_URL, plugin)) |
77
|
|
|
print(indent_stat(stat_export)) |
78
|
|
|
print('') |
79
|
|
|
|
80
|
|
|
|
81
|
|
|
def print_plugin_description(plugin, stat): |
82
|
|
|
if stat.fields_description: |
83
|
|
|
# For each plugins with a description |
84
|
|
|
print('Fields descriptions:') |
85
|
|
|
print('') |
86
|
|
|
for field, description in iteritems(stat.fields_description): |
87
|
|
|
print('* **{}**: {} (unit is *{}*)'.format(field, |
88
|
|
|
description['description'][:-1] if description['description'].endswith('.') else description['description'], |
89
|
|
|
description['unit'])) |
90
|
|
|
print('') |
91
|
|
|
else: |
92
|
|
|
logger.error('No fields_description variable defined for plugin {}'.format(plugin)) |
93
|
|
|
|
94
|
|
|
|
95
|
|
|
def print_plugin_item_value(plugin, stat, stat_export): |
96
|
|
|
item = None |
97
|
|
|
value = None |
98
|
|
|
if isinstance(stat_export, dict): |
99
|
|
|
item = list(stat_export.keys())[0] |
100
|
|
|
value = None |
101
|
|
|
elif isinstance(stat_export, list) and len(stat_export) > 0 and isinstance(stat_export[0], dict): |
102
|
|
|
if 'key' in stat_export[0]: |
103
|
|
|
item = stat_export[0]['key'] |
104
|
|
|
else: |
105
|
|
|
item = list(stat_export[0].keys())[0] |
106
|
|
|
if item and stat.get_stats_item(item): |
107
|
|
|
stat_item = json.loads(stat.get_stats_item(item)) |
108
|
|
|
if isinstance(stat_item[item], list): |
109
|
|
|
value = stat_item[item][0] |
110
|
|
|
else: |
111
|
|
|
value = stat_item[item] |
112
|
|
|
print('Get a specific field::') |
113
|
|
|
print('') |
114
|
|
|
print(' # curl {}/{}/{}'.format(API_URL, plugin, item)) |
115
|
|
|
print(indent_stat(stat_item)) |
116
|
|
|
print('') |
117
|
|
|
if item and value and stat.get_stats_value(item, value): |
118
|
|
|
print('Get a specific item when field matchs the given value::') |
119
|
|
|
print('') |
120
|
|
|
print(' # curl {}/{}/{}/{}'.format(API_URL, plugin, item, value)) |
121
|
|
|
print(indent_stat(json.loads(stat.get_stats_value(item, value)))) |
122
|
|
|
print('') |
123
|
|
|
|
124
|
|
|
|
125
|
|
|
def print_all(): |
126
|
|
|
sub_title = 'GET all stats' |
127
|
|
|
print(sub_title) |
128
|
|
|
print('-' * len(sub_title)) |
129
|
|
|
print('') |
130
|
|
|
print('Get all Glances stats::') |
131
|
|
|
print('') |
132
|
|
|
print(' # curl {}/all'.format(API_URL)) |
133
|
|
|
print(' Return a very big dictionnary (avoid using this request, performances will be poor)...') |
134
|
|
|
print('') |
135
|
|
|
|
136
|
|
|
|
137
|
|
|
def print_history(stats): |
138
|
|
|
time.sleep(1) |
139
|
|
|
stats.update() |
140
|
|
|
time.sleep(1) |
141
|
|
|
stats.update() |
142
|
|
|
sub_title = 'GET stats history' |
143
|
|
|
print(sub_title) |
144
|
|
|
print('-' * len(sub_title)) |
145
|
|
|
print('') |
146
|
|
|
print('History of a plugin::') |
147
|
|
|
print('') |
148
|
|
|
print(' # curl {}/cpu/history'.format(API_URL)) |
149
|
|
|
print(indent_stat(json.loads(stats.get_plugin('cpu').get_stats_history(nb=3)))) |
150
|
|
|
print('') |
151
|
|
|
print('Limit history to last 2 values::') |
152
|
|
|
print('') |
153
|
|
|
print(' # curl {}/cpu/history/2'.format(API_URL)) |
154
|
|
|
print(indent_stat(json.loads(stats.get_plugin('cpu').get_stats_history(nb=2)))) |
155
|
|
|
print('') |
156
|
|
|
print('History for a specific field::') |
157
|
|
|
print('') |
158
|
|
|
print(' # curl {}/cpu/system/history'.format(API_URL)) |
159
|
|
|
print(indent_stat(json.loads(stats.get_plugin('cpu').get_stats_history('system')))) |
160
|
|
|
print('') |
161
|
|
|
print('Limit history for a specific field to last 2 values::') |
162
|
|
|
print('') |
163
|
|
|
print(' # curl {}/cpu/system/history'.format(API_URL)) |
164
|
|
|
print(indent_stat(json.loads(stats.get_plugin('cpu').get_stats_history('system', nb=2)))) |
165
|
|
|
print('') |
166
|
|
|
|
167
|
|
|
|
168
|
|
|
def print_limits(stats): |
169
|
|
|
sub_title = 'GET limits (used for thresholds)' |
170
|
|
|
print(sub_title) |
171
|
|
|
print('-' * len(sub_title)) |
172
|
|
|
print('') |
173
|
|
|
print('All limits/thresholds::') |
174
|
|
|
print('') |
175
|
|
|
print(' # curl {}/all/limits'.format(API_URL)) |
176
|
|
|
print(indent_stat(stats.getAllLimitsAsDict())) |
177
|
|
|
print('') |
178
|
|
|
print('Limits/thresholds for the cpu plugin::') |
179
|
|
|
print('') |
180
|
|
|
print(' # curl {}/cpu/limits'.format(API_URL)) |
181
|
|
|
print(indent_stat(stats.get_plugin('cpu').limits)) |
182
|
|
|
print('') |
183
|
|
|
|
184
|
|
|
|
185
|
|
|
class GlancesStdoutApiDoc(object): |
186
|
|
|
|
187
|
|
|
""" |
188
|
|
|
This class manages the fields description display. |
189
|
|
|
""" |
190
|
|
|
|
191
|
|
|
def __init__(self, config=None, args=None): |
192
|
|
|
# Init |
193
|
|
|
self.config = config |
194
|
|
|
self.args = args |
195
|
|
|
|
196
|
|
|
def end(self): |
197
|
|
|
pass |
198
|
|
|
|
199
|
|
|
def update(self, |
200
|
|
|
stats, |
201
|
|
|
duration=1): |
202
|
|
|
"""Display issue |
203
|
|
|
""" |
204
|
|
|
|
205
|
|
|
# Display header |
206
|
|
|
print(APIDOC_HEADER) |
207
|
|
|
|
208
|
|
|
# Display plugins list |
209
|
|
|
print_plugins_list(sorted(stats._plugins)) |
210
|
|
|
|
211
|
|
|
# Loop over plugins |
212
|
|
|
for plugin in sorted(stats._plugins): |
213
|
|
|
stat = stats.get_plugin(plugin) |
214
|
|
|
stat_export = stat.get_export() |
215
|
|
|
if stat_export is None or stat_export == [] or stat_export == {}: |
216
|
|
|
continue |
217
|
|
|
print_plugin_export(plugin, stat_export) |
218
|
|
|
print_plugin_description(plugin, stat) |
219
|
|
|
print_plugin_item_value(plugin, stat, stat_export) |
220
|
|
|
|
221
|
|
|
# Get all stats |
222
|
|
|
print_all() |
223
|
|
|
|
224
|
|
|
# History |
225
|
|
|
print_history(stats) |
226
|
|
|
|
227
|
|
|
# Limits |
228
|
|
|
print_limits(stats) |
229
|
|
|
|
230
|
|
|
# Return True to exit directly (no refresh) |
231
|
|
|
return True |
232
|
|
|
|