Merge branch 'develop' into issue2225

This commit is contained in:
nicolargo 2023-02-04 14:53:55 +01:00
commit 25c0a1c9a7
40 changed files with 1772 additions and 1163 deletions

View File

@ -104,7 +104,7 @@ jobs:
- name: Retrieve Repository Docker metadata - name: Retrieve Repository Docker metadata
id: docker_meta id: docker_meta
uses: crazy-max/ghaction-docker-meta@v4.1.1 uses: crazy-max/ghaction-docker-meta@v4.3.0
with: with:
images: ${{ env.DEFAULT_DOCKER_IMAGE }} images: ${{ env.DEFAULT_DOCKER_IMAGE }}
labels: | labels: |
@ -136,7 +136,7 @@ jobs:
password: ${{ secrets.DOCKER_TOKEN }} password: ${{ secrets.DOCKER_TOKEN }}
- name: Build and push image - name: Build and push image
uses: docker/build-push-action@v3 uses: docker/build-push-action@v4
with: with:
push: ${{ env.PUSH_BRANCH == 'true' }} push: ${{ env.PUSH_BRANCH == 'true' }}
tags: "${{ env.DEFAULT_DOCKER_IMAGE }}:${{ matrix.os != 'alpine' && format('{0}-', matrix.os) || '' }}${{ matrix.tag.tag }}" tags: "${{ env.DEFAULT_DOCKER_IMAGE }}:${{ matrix.os != 'alpine' && format('{0}-', matrix.os) || '' }}${{ matrix.tag.tag }}"

View File

@ -137,6 +137,11 @@ docker-alpine: ## Generate local docker images (Alpine)
docker build --target minimal -f ./docker-files/alpine.Dockerfile -t glances:local-alpine-minimal . docker build --target minimal -f ./docker-files/alpine.Dockerfile -t glances:local-alpine-minimal .
docker build --target dev -f ./docker-files/alpine.Dockerfile -t glances:local-alpine-dev . docker build --target dev -f ./docker-files/alpine.Dockerfile -t glances:local-alpine-dev .
docker-ubuntu: ## Generate local docker images (Ubuntu)
docker build --target full -f ./docker-files/ubuntu.Dockerfile -t glances:local-ubuntu-full .
docker build --target minimal -f ./docker-files/ubuntu.Dockerfile -t glances:local-ubuntu-minimal .
docker build --target dev -f ./docker-files/ubuntu.Dockerfile -t glances:local-ubuntu-dev .
# =================================================================== # ===================================================================
# Run # Run
# =================================================================== # ===================================================================
@ -159,6 +164,15 @@ run-docker-alpine-full: ## Start Glances Alpine Docker full in console mode
run-docker-alpine-dev: ## Start Glances Alpine Docker dev in console mode run-docker-alpine-dev: ## Start Glances Alpine Docker dev in console mode
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it glances:local-alpine-dev docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it glances:local-alpine-dev
run-docker-ubuntu-minimal: ## Start Glances Ubuntu Docker minimal in console mode
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it glances:local-ubuntu-minimal
run-docker-ubuntu-full: ## Start Glances Ubuntu Docker full in console mode
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it glances:local-ubuntu-full
run-docker-ubuntu-dev: ## Start Glances Ubuntu Docker dev in console mode
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock:ro --pid host --network host -it glances:local-ubuntu-dev
run-webserver: ## Start Glances in Web server mode run-webserver: ## Start Glances in Web server mode
./venv/bin/python -m glances -C ./conf/glances.conf -w ./venv/bin/python -m glances -C ./conf/glances.conf -w

View File

@ -2,11 +2,82 @@
Glances changelog Glances changelog
============================================================================== ==============================================================================
===============
Version 3.4.0
===============
See roadmap here: https://github.com/nicolargo/glances/issues?q=is%3Aopen+is%3Aissue+milestone%3A%22Glances+3.4.0%22
===============
Version 3.3.1.1
===============
Hard patch on the master branch.
Bug corrected:
* "ModuleNotFoundError: No module named 'ujson'" #2246
* Remove surrounding quotes for quoted command arguments #2247 (related to #2239)
=============== ===============
Version 3.3.1 Version 3.3.1
=============== ===============
Under development, see milestone https://github.com/nicolargo/glances/milestone/61 Enhancements:
* Minor change on the help screen
* Refactor some loop in the processes function
* Replace json by ujson #2201
Bug corrected:
* Unable to see docker related information #2180
* CSV export dependent on sort order for docker container cpu #2156
* Error when process list is displayed in Programs mode #2209
* Console formatting permanently messed up when other text printed #2211
* API GET uptime returns formatted string, not seconds as the doc says #2158
* Glances UI is breaking for multiline commands #2189
Documentation and CI:
* Add unitary test for memory profiling
* Update memory profile chart
* Add run-docker-ubuntu-* in Makefile
* The open-web-browser option was missing dashes #2219
* Correct regexp in glances.conf file example
* What is CW from network #2222 (related to discussion #2221)
* Change Glances repology URL
* Add example for the date format
* Correct Flake8 configuration file
* Drop UT for Python 3.5 and 3.6 (no more available in Ubuntu 22.04)
* Correct unitary test with Python 3.5
* Update Makefile with comments
* Update Python minimal requirement for py3nvlm
* Update security policy (user can open private issue directly in Github)
* Add a simple run script. Entry point for IDE debuger
Cyber security update:
* Security alert on ujson < 5.4
* Merge pull request #2243 from nicolargo/renovate/nvidia-cuda-12.x
* Merge pull request #2244 from nicolargo/renovate/crazy-max-ghaction-docker-meta-4.x
* Merge pull request #2228 from nicolargo/renovate/zeroconf-0.x
* Merge pull request #2242 from nicolargo/renovate/crazy-max-ghaction-docker-meta-4.x
* Merge pull request #2239 from mfridge/action-command-split
* Merge pull request #2165 from nicolargo/renovate/zeroconf-0.x
* Merge pull request #2199 from nicolargo/renovate/alpine-3.x
* Merge pull request #2202 from chncaption/oscs_fix_cdr0ts8au51t49so8c6g
* Bump loader-utils from 2.0.0 to 2.0.3 in /glances/outputs/static #2187 - Update Web lib
Contributors for this version:
* Nicolargo
* renovate[bot]
* chncaption
* fkwong
* *mfridge
And also a big thanks to @RazCrimson (https://github.com/RazCrimson) for the support to the Glances community !
=============== ===============
Version 3.3.0.4 Version 3.3.0.4

View File

@ -40,16 +40,22 @@ Glances - An eye on your system
Summary Summary
======= =======
**Glances** is a cross-platform monitoring tool which aims to present a **Glances** is an open-source system cross-platform monitoring tool.
large amount of monitoring information through a curses or Web It allows real-time monitoring of various aspects of your system such as
based interface. The information dynamically adapts depending on the CPU, memory, disk, network usage etc. It also allows monitoring of running processes,
size of the user interface. logged in users, temperatures, voltages, fan speeds etc.
It also supports container monitoring, it supports different container management
systems such as Docker, LXC. The information is presented in an easy to read dashboard
and can also be used for remote monitoring of systems via a web interface or command
line interface. It is easy to install and use and can be customized to show only
the information that you are interested in.
.. image:: https://raw.githubusercontent.com/nicolargo/glances/develop/docs/_static/glances-summary.png .. image:: https://raw.githubusercontent.com/nicolargo/glances/develop/docs/_static/glances-summary.png
It can also work in client/server mode. Remote monitoring could be done In client/server mode, remote monitoring could be done via terminal,
via terminal, Web interface or API (XML-RPC and RESTful). Stats can also Web interface or API (XML-RPC and RESTful).
be exported to files or external time/value databases. Stats can also be exported to files or external time/value databases, CSV or direct
output to STDOUT.
.. image:: https://raw.githubusercontent.com/nicolargo/glances/develop/docs/_static/glances-responsive-webdesign.png .. image:: https://raw.githubusercontent.com/nicolargo/glances/develop/docs/_static/glances-responsive-webdesign.png
@ -111,6 +117,7 @@ Optional dependencies:
- ``py-cpuinfo`` (for the Quicklook CPU info module) - ``py-cpuinfo`` (for the Quicklook CPU info module)
- ``pygal`` (for the graph export module) - ``pygal`` (for the graph export module)
- ``pymdstat`` (for RAID support) [Linux-only] - ``pymdstat`` (for RAID support) [Linux-only]
- ``pymongo`` (for the MongoDB export module) [Only for Python >= 3.7]
- ``pysnmp`` (for SNMP support) - ``pysnmp`` (for SNMP support)
- ``pySMART.smartx`` (for HDD Smart support) [Linux-only] - ``pySMART.smartx`` (for HDD Smart support) [Linux-only]
- ``pyzmq`` (for the ZeroMQ export module) - ``pyzmq`` (for the ZeroMQ export module)

View File

@ -307,6 +307,7 @@ battery_critical=95
#core 0_fans_speed_alias=CPU Core 0 fan #core 0_fans_speed_alias=CPU Core 0 fan
#or #or
#core 0_alias=CPU Core 0 #core 0_alias=CPU Core 0
#core 1_alias=CPU Core 1
[processcount] [processcount]
disable=False disable=False
@ -583,6 +584,15 @@ db=glances
#user=root #user=root
#password=root #password=root
[mongodb]
# Configuration for the --export mongodb option
# https://www.mongodb.com
host=localhost
port=27017
db=glances
user=root
password=example
[kafka] [kafka]
# Configuration for the --export kafka option # Configuration for the --export kafka option
# http://kafka.apache.org/ # http://kafka.apache.org/

View File

@ -9,3 +9,4 @@ codespell
memory-profiler memory-profiler
matplotlib matplotlib
setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability setuptools>=65.5.1 # not directly required, pinned by Snyk to avoid a vulnerability
numpy>=1.22.2 # not directly required, pinned by Snyk to avoid a vulnerability

View File

@ -10,8 +10,10 @@ refresh=2
# Does Glances should check if a newer version is available on PyPI ? # Does Glances should check if a newer version is available on PyPI ?
check_update=false check_update=false
# History size (maximum number of values) # History size (maximum number of values)
# Default is 3600 seconds (1 hour) # Default is 1200 values (~1h with the default refresh rate)
history_size=3600 history_size=1200
# Set the way Glances should display the date (default is %Y-%m-%d %H:%M:%S %Z)
#strftime_format="%Y-%m-%d %H:%M:%S %Z"
############################################################################## ##############################################################################
# User interface # User interface
@ -212,7 +214,7 @@ critical=-85
disable=False disable=False
# Define the list of hidden disks (comma-separated regexp) # Define the list of hidden disks (comma-separated regexp)
#hide=sda2,sda5,loop.* #hide=sda2,sda5,loop.*
hide=loop.*,/dev/loop* hide=loop.*,/dev/loop.*
# Define the list of disks to be show (comma-separated) # Define the list of disks to be show (comma-separated)
#show=sda.* #show=sda.*
# Alias for sda1 # Alias for sda1
@ -582,6 +584,15 @@ db=glances
#user=root #user=root
#password=root #password=root
[mongodb]
# Configuration for the --export mongodb option
# https://www.mongodb.com
host=localhost
port=27017
db=glances
user=root
password=example
[kafka] [kafka]
# Configuration for the --export kafka option # Configuration for the --export kafka option
# http://kafka.apache.org/ # http://kafka.apache.org/

View File

@ -26,6 +26,7 @@ RUN apk add --no-cache \
curl \ curl \
lm-sensors \ lm-sensors \
wireless-tools \ wireless-tools \
smartmontools \
iputils iputils
############################################################################## ##############################################################################
@ -89,9 +90,11 @@ RUN apk add --no-cache \
python3 \ python3 \
py3-packaging \ py3-packaging \
py3-dateutil \ py3-dateutil \
py3-requests \
curl \ curl \
lm-sensors \ lm-sensors \
wireless-tools \ wireless-tools \
smartmontools \
iputils iputils
COPY --from=buildRequirements /root/.local/bin /usr/local/bin/ COPY --from=buildRequirements /root/.local/bin /usr/local/bin/

View File

@ -0,0 +1,146 @@
#
# Glances Dockerfile (based on Ubuntu)
#
# https://github.com/nicolargo/glances
#
# WARNING: the versions should be set.
# Ex: Python 3.10 for Ubuntu 22.04
# Note: ENV is for future running containers. ARG for building your Docker image.
ARG IMAGE_VERSION=12.0.1-base-ubuntu22.04
ARG PYTHON_VERSION=3.10
ARG PIP_MIRROR=https://mirrors.aliyun.com/pypi/simple/
FROM nvidia/cuda:${IMAGE_VERSION} as build
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
python3 \
python3-dev \
python3-pip \
python3-wheel \
musl-dev \
build-essential \
libzmq5 \
curl \
lm-sensors \
wireless-tools \
smartmontools \
net-tools \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
##############################################################################
# Install the dependencies beforehand to make them cacheable
FROM build as buildRequirements
ARG PYTHON_VERSION
ARG PIP_MIRROR
ARG PIP_MIRROR=https://mirrors.aliyun.com/pypi/simple/
COPY requirements.txt .
RUN python${PYTHON_VERSION} -m pip install --no-cache-dir --user -r requirements.txt -i ${PIP_MIRROR}
# Minimal means no webui, but it break what is done previously (see #2155)
# So install the webui requirements...
COPY webui-requirements.txt .
RUN python${PYTHON_VERSION} -m pip install --no-cache-dir --user -r webui-requirements.txt -i ${PIP_MIRROR}
# As minimal image we want to monitor others docker containers
RUN python${PYTHON_VERSION} -m pip install --no-cache-dir --user docker -i ${PIP_MIRROR}
# Force install otherwise it could be cached without rerun
ARG CHANGING_ARG
RUN python${PYTHON_VERSION} -m pip install --no-cache-dir --user glances -i ${PIP_MIRROR}
##############################################################################
FROM build as buildOptionalRequirements
ARG PYTHON_VERSION
ARG PIP_MIRROR
COPY requirements.txt .
COPY optional-requirements.txt .
RUN CASS_DRIVER_NO_CYTHON=1 pip3 install --no-cache-dir --user -r optional-requirements.txt -i ${PIP_MIRROR}
##############################################################################
# full image
##############################################################################
FROM build as full
ARG PYTHON_VERSION
COPY --from=buildRequirements /root/.local/bin /root/.local/bin/
COPY --from=buildRequirements /root/.local/lib/python${PYTHON_VERSION}/site-packages /root/.local/lib/python${PYTHON_VERSION}/site-packages/
COPY --from=buildOptionalRequirements /root/.local/lib/python${PYTHON_VERSION}/site-packages /root/.local/lib/python${PYTHON_VERSION}/site-packages/
COPY ./docker-compose/glances.conf /etc/glances.conf
# EXPOSE PORT (XMLRPC / WebUI)
EXPOSE 61209 61208
# Define default command.
WORKDIR /glances
CMD python3 -m glances -C /etc/glances.conf $GLANCES_OPT
##############################################################################
# minimal image
##############################################################################
# Create running images without any building dependency
FROM nvidia/cuda:${IMAGE_VERSION} as minimal
ARG PYTHON_VERSION
ARG DEBIAN_FRONTEND=noninteractive
ENV TZ=Asia/Shanghai
RUN apt-get update \
&& apt-get install -y --no-install-recommends \
python3 \
python3-packaging \
python3-dateutil \
python3-requests \
curl \
lm-sensors \
wireless-tools \
smartmontools \
net-tools \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
COPY --from=buildRequirements /root/.local/bin /root/.local/bin/
COPY --from=buildRequirements /root/.local/lib/python${PYTHON_VERSION}/site-packages /root/.local/lib/python${PYTHON_VERSION}/site-packages/
COPY ./docker-compose/glances.conf /etc/glances.conf
# EXPOSE PORT (XMLRPC / WebUI)
EXPOSE 61209 61208
# Define default command.
WORKDIR /glances
CMD python3 -m glances -C /etc/glances.conf $GLANCES_OPT
##############################################################################
# dev image
##############################################################################
FROM full as dev
ARG PYTHON_VERSION
COPY --from=buildRequirements /root/.local/bin /root/.local/bin/
COPY --from=buildRequirements /root/.local/lib/python${PYTHON_VERSION}/site-packages /root/.local/lib/python${PYTHON_VERSION}/site-packages/
COPY --from=buildOptionalRequirements /root/.local/lib/python${PYTHON_VERSION}/site-packages /root/.local/lib/python${PYTHON_VERSION}/site-packages/
COPY ./docker-compose/glances.conf /etc/glances.conf
# Copy the current Glances source code
COPY . /glances
# EXPOSE PORT (XMLRPC / WebUI)
EXPOSE 61209 61208
# Forward access and error logs to Docker's log collector
RUN ln -sf /dev/stdout /tmp/glances-root.log \
&& ln -sf /dev/stderr /var/log/error.log
# Define default command.
WORKDIR /glances
CMD python3 -m glances -C /etc/glances.conf $GLANCES_OPT

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -37,3 +37,9 @@ or another example:
[diskio] [diskio]
show=sda.* show=sda.*
Filtering is based on regular expression. Please be sure that your regular
expression works as expected. You can use an online tool like `regex101`_ in
order to test your regular expression.
.. _regex101: https://regex101.com/

View File

@ -47,4 +47,9 @@ under the ``[docker]`` section:
You can use all the variables ({{foo}}) available in the Docker plugin. You can use all the variables ({{foo}}) available in the Docker plugin.
Filtering (for hide or show) is based on regular expression. Please be sure that your regular
expression works as expected. You can use an online tool like `regex101`_ in
order to test your regular expression.
.. _regex101: https://regex101.com/
.. _docker-py: https://github.com/docker/docker-py .. _docker-py: https://github.com/docker/docker-py

View File

@ -53,3 +53,9 @@ Example to only show /dev/sdb mount points:
[fs] [fs]
show=/dev/sdb.* show=/dev/sdb.*
Filtering is based on regular expression. Please be sure that your regular
expression works as expected. You can use an online tool like `regex101`_ in
order to test your regular expression.
.. _regex101: https://regex101.com/

View File

@ -22,7 +22,9 @@ file under the ``[ip]`` section:
**NOTE:** Setting low values for `public_refresh_interval` will result in frequent **NOTE:** Setting low values for `public_refresh_interval` will result in frequent
HTTP requests to the IP detection servers. Recommended range: 120-600 seconds HTTP requests to the IP detection servers. Recommended range: 120-600 seconds.
Glances uses online services in order to get the IP addresses. Your IP address could be
blocked if too many requests are done.
If the Censys options are configured, the public IP address is also analysed (with the same interval) If the Censys options are configured, the public IP address is also analysed (with the same interval)
and additional information is displayed. and additional information is displayed.

View File

@ -53,3 +53,9 @@ virtual docker interface (docker0, docker1, ...):
wlan0_tx_warning=900000 wlan0_tx_warning=900000
wlan0_tx_critical=1000000 wlan0_tx_critical=1000000
wlan0_tx_log=True wlan0_tx_log=True
Filtering is based on regular expression. Please be sure that your regular
expression works as expected. You can use an online tool like `regex101`_ in
order to test your regular expression.
.. _regex101: https://regex101.com/

File diff suppressed because it is too large Load Diff

View File

@ -9,42 +9,35 @@ following:
.. code-block:: ini .. code-block:: ini
[couchdb] [mongodb]
host=localhost host=localhost
port=5984 port=27017
user=root
password=root
db=glances db=glances
user=root
password=example
and run Glances with: and run Glances with:
.. code-block:: console .. code-block:: console
$ glances --export couchdb $ glances --export mongodb
Documents are stored in native ``JSON`` format. Glances adds ``"type"`` Documents are stored in native the configured database (glances by default)
and ``"time"`` entries: with one collection per plugin.
- ``type``: plugin name Example of MongoDB Document for the load stats:
- ``time``: timestamp (format: "2016-09-24T16:39:08.524828Z")
Example of Couch Document for the load stats:
.. code-block:: json .. code-block:: json
{ {
"_id": "36cbbad81453c53ef08804cb2612d5b6", _id: ObjectId('63d78ffee5528e543ce5af3a'),
"_rev": "1-382400899bec5615cabb99aa34df49fb", min1: 1.46337890625,
"min15": 0.33, min5: 1.09619140625,
"time": "2016-09-24T16:39:08.524828Z", min15: 1.07275390625,
"min5": 0.4, cpucore: 4,
"cpucore": 4, history_size: 1200,
"load_warning": 1, load_disable: 'False',
"min1": 0.5, load_careful: 0.7,
"history_size": 28800, load_warning: 1,
"load_critical": 5, load_critical: 5
"type": "load",
"load_careful": 0.7
} }
You can view the result using the CouchDB utils URL: http://127.0.0.1:5984/_utils/database.html?glances.

View File

@ -18,6 +18,7 @@ to providing stats to multiple services (see list below).
json json
kafka kafka
mqtt mqtt
mongodb
opentsdb opentsdb
prometheus prometheus
rabbitmq rabbitmq

50
docs/gw/mongodb.rst Normal file
View File

@ -0,0 +1,50 @@
.. _couchdb:
MongoDB
=======
You can export statistics to a ``MongoDB`` server.
The connection should be defined in the Glances configuration file as
following:
.. code-block:: ini
[couchdb]
host=localhost
port=
user=root
password=example
db=glances
and run Glances with:
.. code-block:: console
$ glances --export couchdb
Documents are stored in native ``JSON`` format. Glances adds ``"type"``
and ``"time"`` entries:
- ``type``: plugin name
- ``time``: timestamp (format: "2016-09-24T16:39:08.524828Z")
Example of Couch Document for the load stats:
.. code-block:: json
{
"_id": "36cbbad81453c53ef08804cb2612d5b6",
"_rev": "1-382400899bec5615cabb99aa34df49fb",
"min15": 0.33,
"time": "2016-09-24T16:39:08.524828Z",
"min5": 0.4,
"cpucore": 4,
"load_warning": 1,
"min1": 0.5,
"history_size": 28800,
"load_critical": 5,
"type": "load",
"load_careful": 0.7
}
You can view the result using the CouchDB utils URL: http://127.0.0.1:5984/_utils/database.html?glances.

View File

@ -27,7 +27,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u .in \\n[rst2man-indent\\n[rst2man-indent-level]]u
.. ..
.TH "GLANCES" "1" "Dec 21, 2022" "3.3.1_beta1" "Glances" .TH "GLANCES" "1" "Jan 30, 2023" "3.4.0_beta1" "Glances"
.SH NAME .SH NAME
glances \- An eye on your system glances \- An eye on your system
.SH SYNOPSIS .SH SYNOPSIS
@ -258,7 +258,7 @@ set the server cache time [default: 1 sec]
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
.TP .TP
.B open\-web\-browser .B \-\-open\-web\-browser
try to open the Web UI in the default Web browser try to open the Web UI in the default Web browser
.UNINDENT .UNINDENT
.INDENT 0.0 .INDENT 0.0
@ -732,60 +732,60 @@ format):
.nf .nf
.ft C .ft C
{ {
"version": 1, \(dqversion\(dq: 1,
"disable_existing_loggers": "False", \(dqdisable_existing_loggers\(dq: \(dqFalse\(dq,
"root": { \(dqroot\(dq: {
"level": "INFO", \(dqlevel\(dq: \(dqINFO\(dq,
"handlers": ["file", "console"] \(dqhandlers\(dq: [\(dqfile\(dq, \(dqconsole\(dq]
}, },
"formatters": { \(dqformatters\(dq: {
"standard": { \(dqstandard\(dq: {
"format": "%(asctime)s \-\- %(levelname)s \-\- %(message)s" \(dqformat\(dq: \(dq%(asctime)s \-\- %(levelname)s \-\- %(message)s\(dq
}, },
"short": { \(dqshort\(dq: {
"format": "%(levelname)s: %(message)s" \(dqformat\(dq: \(dq%(levelname)s: %(message)s\(dq
}, },
"free": { \(dqfree\(dq: {
"format": "%(message)s" \(dqformat\(dq: \(dq%(message)s\(dq
} }
}, },
"handlers": { \(dqhandlers\(dq: {
"file": { \(dqfile\(dq: {
"level": "DEBUG", \(dqlevel\(dq: \(dqDEBUG\(dq,
"class": "logging.handlers.RotatingFileHandler", \(dqclass\(dq: \(dqlogging.handlers.RotatingFileHandler\(dq,
"formatter": "standard", \(dqformatter\(dq: \(dqstandard\(dq,
"filename": "/var/tmp/glances.log" \(dqfilename\(dq: \(dq/var/tmp/glances.log\(dq
}, },
"console": { \(dqconsole\(dq: {
"level": "CRITICAL", \(dqlevel\(dq: \(dqCRITICAL\(dq,
"class": "logging.StreamHandler", \(dqclass\(dq: \(dqlogging.StreamHandler\(dq,
"formatter": "free" \(dqformatter\(dq: \(dqfree\(dq
} }
}, },
"loggers": { \(dqloggers\(dq: {
"debug": { \(dqdebug\(dq: {
"handlers": ["file", "console"], \(dqhandlers\(dq: [\(dqfile\(dq, \(dqconsole\(dq],
"level": "DEBUG" \(dqlevel\(dq: \(dqDEBUG\(dq
}, },
"verbose": { \(dqverbose\(dq: {
"handlers": ["file", "console"], \(dqhandlers\(dq: [\(dqfile\(dq, \(dqconsole\(dq],
"level": "INFO" \(dqlevel\(dq: \(dqINFO\(dq
}, },
"standard": { \(dqstandard\(dq: {
"handlers": ["file"], \(dqhandlers\(dq: [\(dqfile\(dq],
"level": "INFO" \(dqlevel\(dq: \(dqINFO\(dq
}, },
"requests": { \(dqrequests\(dq: {
"handlers": ["file", "console"], \(dqhandlers\(dq: [\(dqfile\(dq, \(dqconsole\(dq],
"level": "ERROR" \(dqlevel\(dq: \(dqERROR\(dq
}, },
"elasticsearch": { \(dqelasticsearch\(dq: {
"handlers": ["file", "console"], \(dqhandlers\(dq: [\(dqfile\(dq, \(dqconsole\(dq],
"level": "ERROR" \(dqlevel\(dq: \(dqERROR\(dq
}, },
"elasticsearch.trace": { \(dqelasticsearch.trace\(dq: {
"handlers": ["file", "console"], \(dqhandlers\(dq: [\(dqfile\(dq, \(dqconsole\(dq],
"level": "ERROR" \(dqlevel\(dq: \(dqERROR\(dq
} }
} }
} }
@ -885,6 +885,6 @@ $ glances browser
.sp .sp
Nicolas Hennion aka Nicolargo <\fI\%contact@nicolargo.com\fP> Nicolas Hennion aka Nicolargo <\fI\%contact@nicolargo.com\fP>
.SH COPYRIGHT .SH COPYRIGHT
2022, Nicolas Hennion 2023, Nicolas Hennion
.\" Generated by docutils manpage writer. .\" Generated by docutils manpage writer.
. .

View File

@ -19,7 +19,7 @@ import sys
# Global name # Global name
# Version should start and end with a numerical char # Version should start and end with a numerical char
# See https://packaging.python.org/specifications/core-metadata/#version # See https://packaging.python.org/specifications/core-metadata/#version
__version__ = '3.3.1_beta1' __version__ = '3.4.0_beta1'
__author__ = 'Nicolas Hennion <nicolas@nicolargo.com>' __author__ = 'Nicolas Hennion <nicolas@nicolargo.com>'
__license__ = 'LGPLv3' __license__ = 'LGPLv3'

View File

@ -1,4 +1,3 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Glances - An eye on your system # Glances - An eye on your system

View File

@ -75,7 +75,7 @@ class GlancesClientBrowser(object):
# Try with the preconfigure password (only if status is PROTECTED) # Try with the preconfigure password (only if status is PROTECTED)
clear_password = self.password.get_password(server['name']) clear_password = self.password.get_password(server['name'])
if clear_password is not None: if clear_password is not None:
server['password'] = self.password.sha256_hash(clear_password) server['password'] = self.password.get_hash(clear_password)
return 'http://{}:{}@{}:{}'.format(server['username'], server['password'], server['ip'], server['port']) return 'http://{}:{}@{}:{}'.format(server['username'], server['password'], server['ip'], server['port'])
else: else:
return 'http://{}:{}'.format(server['ip'], server['port']) return 'http://{}:{}'.format(server['ip'], server['port'])
@ -151,7 +151,7 @@ class GlancesClientBrowser(object):
) )
# Store the password for the selected server # Store the password for the selected server
if clear_password is not None: if clear_password is not None:
self.set_in_selected('password', self.password.sha256_hash(clear_password)) self.set_in_selected('password', self.password.get_hash(clear_password))
# Display the Glance client on the selected server # Display the Glance client on the selected server
logger.info("Connect Glances client to the {} server".format(server['key'])) logger.info("Connect Glances client to the {} server".format(server['key']))

View File

@ -68,6 +68,10 @@ if PY3:
return s.decode() return s.decode()
return s.encode('ascii', 'ignore').decode() return s.encode('ascii', 'ignore').decode()
def to_hex(s):
"""Convert the bytes string to a hex string"""
return s.hex()
def listitems(d): def listitems(d):
return list(d.items()) return list(d.items())
@ -166,6 +170,10 @@ else:
return s return s
return unicodedata.normalize('NFKD', s).encode('ascii', 'ignore') return unicodedata.normalize('NFKD', s).encode('ascii', 'ignore')
def to_hex(s):
"""Convert the string to a hex string in Python 2"""
return s.encode('hex')
def listitems(d): def listitems(d):
return d.items() return d.items()

View File

@ -81,10 +81,10 @@ class Export(GlancesExport):
# Loop over plugins to export # Loop over plugins to export
for plugin in self.plugins_to_export(stats): for plugin in self.plugins_to_export(stats):
if isinstance(all_stats[plugin], list): if isinstance(all_stats[plugin], list):
for stat in all_stats[plugin]: for stat in sorted(all_stats[plugin], key=lambda x: x['key']):
# First line: header # First line: header
if self.first_line: if self.first_line:
csv_header += ('{}_{}_{}'.format(plugin, self.get_item_key(stat), item) for item in stat) csv_header += ['{}_{}_{}'.format(plugin, self.get_item_key(stat), item) for item in stat]
# Others lines: stats # Others lines: stats
csv_data += itervalues(stat) csv_data += itervalues(stat)
elif isinstance(all_stats[plugin], dict): elif isinstance(all_stats[plugin], dict):

View File

@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
#
# This file is part of Glances.
#
# SPDX-FileCopyrightText: 2023 Nicolas Hennion <nicolas@nicolargo.com>
#
# SPDX-License-Identifier: LGPL-3.0-only
#
"""MongoDB interface class."""
import sys
from datetime import datetime
from glances.logger import logger
from glances.exports.glances_export import GlancesExport
import pymongo
from urllib.parse import quote_plus
class Export(GlancesExport):
"""This class manages the MongoDB export module."""
def __init__(self, config=None, args=None):
"""Init the MongoDB export IF."""
super(Export, self).__init__(config=config, args=args)
# Mandatory configuration keys (additional to host and port)
self.db = None
# Optional configuration keys
self.user = None
self.password = None
# Load the Cassandra configuration file section
self.export_enable = self.load_conf('mongodb', mandatories=['host', 'port', 'db'], options=['user', 'password'])
if not self.export_enable:
sys.exit(2)
# Init the CouchDB client
self.client = self.init()
def init(self):
"""Init the connection to the CouchDB server."""
if not self.export_enable:
return None
server_uri = 'mongodb://%s:%s@%s:%s' % (quote_plus(self.user),
quote_plus(self.password),
self.host,
self.port)
try:
client = pymongo.MongoClient(server_uri)
client.admin.command('ping')
except Exception as e:
logger.critical("Cannot connect to MongoDB server %s:%s (%s)" % (self.host, self.port, e))
sys.exit(2)
else:
logger.info("Connected to the MongoDB server")
return client
def database(self):
"""Return the CouchDB database object"""
return self.client[self.db]
def export(self, name, columns, points):
"""Write the points to the MongoDB server."""
logger.debug("Export {} stats to MongoDB".format(name))
# Create DB input
data = dict(zip(columns, points))
# Write data to the MongoDB database
try:
self.database()[name].insert_one(data)
except Exception as e:
logger.error("Cannot export {} stats to MongoDB ({})".format(name, e))

View File

@ -127,8 +127,10 @@ class GlancesBottle(object):
if username == self.args.username: if username == self.args.username:
from glances.password import GlancesPassword from glances.password import GlancesPassword
pwd = GlancesPassword(username=username, config=self.config) pwd = GlancesPassword(username=username,
return pwd.check_password(self.args.password, pwd.sha256_hash(password)) config=self.config)
return pwd.check_password(self.args.password,
pwd.get_hash(password))
else: else:
return False return False
@ -160,6 +162,7 @@ class GlancesBottle(object):
'/api/%s/<plugin>/<item>/history/<nb:int>' % self.API_VERSION, method="GET", callback=self._api_item_history '/api/%s/<plugin>/<item>/history/<nb:int>' % self.API_VERSION, method="GET", callback=self._api_item_history
) )
self._app.route('/api/%s/<plugin>/<item>/<value>' % self.API_VERSION, method="GET", callback=self._api_value) self._app.route('/api/%s/<plugin>/<item>/<value>' % self.API_VERSION, method="GET", callback=self._api_value)
self._app.route('/api/%s/<plugin>/<item>/<value:path>' % self.API_VERSION, method="GET", callback=self._api_value)
bindmsg = 'Glances RESTful API Server started on {}api/{}/'.format(self.bind_url, self.API_VERSION) bindmsg = 'Glances RESTful API Server started on {}api/{}/'.format(self.bind_url, self.API_VERSION)
logger.info(bindmsg) logger.info(bindmsg)

View File

@ -123,6 +123,7 @@
v-if="!args.disable_sensors" v-if="!args.disable_sensors"
:data="data" :data="data"
></glances-plugin-sensors> ></glances-plugin-sensors>
<glances-plugin-now :data="data"></glances-plugin-now>
</div> </div>
</div> </div>
<div class="col-sm-18"> <div class="col-sm-18">
@ -138,13 +139,6 @@
</div> </div>
</div> </div>
</div> </div>
<div class="container-fluid">
<div class="row">
<div class="col-sm-24">
<glances-plugin-now :data="data"></glances-plugin-now>
</div>
</div>
</div>
</main> </main>
</template> </template>

File diff suppressed because it is too large Load Diff

View File

@ -3,27 +3,27 @@
"dependencies": { "dependencies": {
"bootstrap": "^3.4.1", "bootstrap": "^3.4.1",
"favico.js": "^0.3.10", "favico.js": "^0.3.10",
"hotkeys-js": "^3.10.0", "hotkeys-js": "^3.10.1",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"sanitize-html": "^2.7.2", "sanitize-html": "^2.8.1",
"vue": "^3.2.41" "vue": "^3.2.45"
}, },
"devDependencies": { "devDependencies": {
"copy-webpack-plugin": "^11.0.0", "copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.7.1", "css-loader": "^6.7.3",
"del": "^7.0.0", "del": "^7.0.0",
"eslint": "^8.25.0", "eslint": "^8.32.0",
"eslint-plugin-vue": "^9.6.0", "eslint-plugin-vue": "^9.9.0",
"html-webpack-plugin": "^5.5.0", "html-webpack-plugin": "^5.5.0",
"less": "^4.1.3", "less": "^4.1.3",
"less-loader": "^11.1.0", "less-loader": "^11.1.0",
"sass": "^1.55.0", "sass": "^1.57.1",
"sass-loader": "^13.1.0", "sass-loader": "^13.2.0",
"style-loader": "^3.3.1", "style-loader": "^3.3.1",
"url-loader": "^4.1.1", "url-loader": "^4.1.1",
"vue-loader": "^17.0.0", "vue-loader": "^17.0.1",
"webpack": "^5.74.0", "webpack": "^5.75.0",
"webpack-cli": "^4.10.0", "webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.11.1" "webpack-dev-server": "^4.11.1"
}, },
"scripts": { "scripts": {

File diff suppressed because one or more lines are too long

View File

@ -16,7 +16,7 @@ import sys
import uuid import uuid
from io import open from io import open
from glances.compat import b, input from glances.compat import b, input, to_hex
from glances.config import user_config_dir from glances.config import user_config_dir
from glances.globals import safe_makedirs from glances.globals import safe_makedirs
from glances.logger import logger from glances.logger import logger
@ -36,25 +36,26 @@ class GlancesPassword(object):
def local_password_path(self): def local_password_path(self):
"""Return the local password path. """Return the local password path.
Related toissue: Password files in same configuration dir in effect #2143 Related to issue: Password files in same configuration dir in effect #2143
""" """
if self.config is None: if self.config is None:
return user_config_dir() return user_config_dir()
else: else:
return self.config.get_value('passwords', 'local_password_path', default=user_config_dir()) return self.config.get_value('passwords', 'local_password_path', default=user_config_dir())
def sha256_hash(self, plain_password): def get_hash(self, plain_password, salt=''):
"""Return the SHA-256 of the given password.""" """Return the hashed password, salt + pbkdf2_hmac."""
return hashlib.sha256(b(plain_password)).hexdigest() return to_hex(hashlib.pbkdf2_hmac('sha256',
plain_password.encode(),
def get_hash(self, salt, plain_password): salt.encode(),
"""Return the hashed password, salt + SHA-256.""" 100000,
return hashlib.sha256(salt.encode() + plain_password.encode()).hexdigest() dklen=128))
def hash_password(self, plain_password): def hash_password(self, plain_password):
"""Hash password with a salt based on UUID (universally unique identifier).""" """Hash password with a salt based on UUID (universally unique identifier)."""
salt = uuid.uuid4().hex salt = uuid.uuid4().hex
encrypted_password = self.get_hash(salt, plain_password) encrypted_password = self.get_hash(plain_password,
salt=salt)
return salt + '$' + encrypted_password return salt + '$' + encrypted_password
def check_password(self, hashed_password, plain_password): def check_password(self, hashed_password, plain_password):
@ -63,7 +64,8 @@ class GlancesPassword(object):
Return the comparison with the encrypted_password. Return the comparison with the encrypted_password.
""" """
salt, encrypted_password = hashed_password.split('$') salt, encrypted_password = hashed_password.split('$')
re_encrypted_password = self.get_hash(salt, plain_password) re_encrypted_password = self.get_hash(plain_password,
salt = salt)
return encrypted_password == re_encrypted_password return encrypted_password == re_encrypted_password
def get_password(self, description='', confirm=False, clear=False): def get_password(self, description='', confirm=False, clear=False):
@ -72,11 +74,11 @@ class GlancesPassword(object):
For Glances server, get the password (confirm=True, clear=False): For Glances server, get the password (confirm=True, clear=False):
1) from the password file (if it exists) 1) from the password file (if it exists)
2) from the CLI 2) from the CLI
Optionally: save the password to a file (hashed with salt + SHA-256) Optionally: save the password to a file (hashed with salt + SHA-pbkdf2_hmac)
For Glances client, get the password (confirm=False, clear=True): For Glances client, get the password (confirm=False, clear=True):
1) from the CLI 1) from the CLI
2) the password is hashed with SHA-256 (only SHA string transit 2) the password is hashed with SHA-pbkdf2_hmac (only SHA string transit
through the network) through the network)
""" """
if os.path.exists(self.password_file) and not clear: if os.path.exists(self.password_file) and not clear:
@ -84,21 +86,21 @@ class GlancesPassword(object):
logger.info("Read password from file {}".format(self.password_file)) logger.info("Read password from file {}".format(self.password_file))
password = self.load_password() password = self.load_password()
else: else:
# password_sha256 is the plain SHA-256 password # password_hash is the plain SHA-pbkdf2_hmac password
# password_hashed is the salt + SHA-256 password # password_hashed is the salt + SHA-pbkdf2_hmac password
password_sha256 = self.sha256_hash(getpass.getpass(description)) password_hash = self.get_hash(getpass.getpass(description))
password_hashed = self.hash_password(password_sha256) password_hashed = self.hash_password(password_hash)
if confirm: if confirm:
# password_confirm is the clear password (only used to compare) # password_confirm is the clear password (only used to compare)
password_confirm = self.sha256_hash(getpass.getpass('Password (confirm): ')) password_confirm = self.get_hash(getpass.getpass('Password (confirm): '))
if not self.check_password(password_hashed, password_confirm): if not self.check_password(password_hashed, password_confirm):
logger.critical("Sorry, passwords do not match. Exit.") logger.critical("Sorry, passwords do not match. Exit.")
sys.exit(1) sys.exit(1)
# Return the plain SHA-256 or the salted password # Return the plain SHA-pbkdf2_hmac or the salted password
if clear: if clear:
password = password_sha256 password = password_hash
else: else:
password = password_hashed password = password_hashed

View File

@ -29,50 +29,26 @@ import psutil
# 'key': 'interface_name'} # 'key': 'interface_name'}
# Fields description # Fields description
fields_description = { fields_description = {
'interface_name': { 'interface_name': {'description': 'Interface name.', 'unit': 'string'},
'description': 'Interface name.', 'alias': {'description': 'Interface alias name (optional).', 'unit': 'string'},
'unit': 'string' 'rx': {'description': 'The received/input rate (in bit per second).', 'unit': 'bps'},
}, 'tx': {'description': 'The sent/output rate (in bit per second).', 'unit': 'bps'},
'alias': { 'cx': {'description': 'The cumulative received+sent rate (in bit per second).', 'unit': 'bps'},
'description': 'Interface alias name (optional).',
'unit': 'string'
},
'rx': {
'description': 'The received/input rate (in bit per second).',
'unit': 'bps'
},
'tx': {
'description': 'The sent/output rate (in bit per second).',
'unit': 'bps'
},
'cx': {
'description': 'The cumulative received+sent rate (in bit per second).',
'unit': 'bps'
},
'cumulative_rx': { 'cumulative_rx': {
'description': 'The number of bytes received through the interface (cumulative).', 'description': 'The number of bytes received through the interface (cumulative).',
'unit': 'bytes', 'unit': 'bytes',
}, },
'cumulative_tx': { 'cumulative_tx': {'description': 'The number of bytes sent through the interface (cumulative).', 'unit': 'bytes'},
'description': 'The number of bytes sent through the interface (cumulative).',
'unit': 'bytes'
},
'cumulative_cx': { 'cumulative_cx': {
'description': 'The cumulative number of bytes reveived and sent through the interface (cumulative).', 'description': 'The cumulative number of bytes reveived and sent through the interface (cumulative).',
'unit': 'bytes' 'unit': 'bytes',
}, },
'speed': { 'speed': {
'description': 'Maximum interface speed (in bit per second). Can return 0 on some operating-system.', 'description': 'Maximum interface speed (in bit per second). Can return 0 on some operating-system.',
'unit': 'bps', 'unit': 'bps',
}, },
'is_up': { 'is_up': {'description': 'Is the interface up ?', 'unit': 'bool'},
'description': 'Is the interface up ?', 'time_since_update': {'description': 'Number of seconds since last update.', 'unit': 'seconds'},
'unit': 'bool'
},
'time_since_update': {
'description': 'Number of seconds since last update.',
'unit': 'seconds'
},
} }
# SNMP OID # SNMP OID

View File

@ -383,17 +383,19 @@ class GlancesProcesses(object):
# Build the processes stats list (it is why we need psutil>=5.3.0) # Build the processes stats list (it is why we need psutil>=5.3.0)
# This is one of the main bottleneck of Glances (see flame graph) # This is one of the main bottleneck of Glances (see flame graph)
# Filter processes # Filter processes
self.processlist = list(filter(lambda p: not (BSD and p.info['name'] == 'idle') and self.processlist = list(
not (WINDOWS and p.info['name'] == 'System Idle Process') and filter(
not (MACOS and p.info['name'] == 'kernel_task') and lambda p: not (BSD and p.info['name'] == 'idle')
not (self.no_kernel_threads and LINUX and p.info['gids'].real == 0), and not (WINDOWS and p.info['name'] == 'System Idle Process')
psutil.process_iter(attrs=sorted_attrs, ad_value=None))) and not (MACOS and p.info['name'] == 'kernel_task')
and not (self.no_kernel_threads and LINUX and p.info['gids'].real == 0),
psutil.process_iter(attrs=sorted_attrs, ad_value=None),
)
)
# Only get the info key # Only get the info key
self.processlist = [p.info for p in self.processlist] self.processlist = [p.info for p in self.processlist]
# Sort the processes list by the current sort_key # Sort the processes list by the current sort_key
self.processlist = sort_stats(self.processlist, self.processlist = sort_stats(self.processlist, sorted_by=self.sort_key, reverse=True)
sorted_by=self.sort_key,
reverse=True)
# Update the processcount # Update the processcount
self.update_processcount(self.processlist) self.update_processcount(self.processlist)
@ -470,8 +472,7 @@ class GlancesProcesses(object):
self.processlist_cache[proc['pid']] = {cached: proc[cached] for cached in cached_attrs} self.processlist_cache[proc['pid']] = {cached: proc[cached] for cached in cached_attrs}
# Apply user filter # Apply user filter
self.processlist = list(filter(lambda p: not self._filter.is_filtered(p), self.processlist = list(filter(lambda p: not self._filter.is_filtered(p), self.processlist))
self.processlist))
# Compute the maximum value for keys in self._max_values_list: CPU, MEM # Compute the maximum value for keys in self._max_values_list: CPU, MEM
# Useful to highlight the processes with maximum values # Useful to highlight the processes with maximum values

View File

@ -36,7 +36,7 @@ def processes_to_programs(processes):
'name': p['name'], 'name': p['name'],
'cmdline': [p['name']], 'cmdline': [p['name']],
'pid': '_', 'pid': '_',
'username': p['username'], 'username': p['username'] if 'username' in p else '_',
'nice': p['nice'], 'nice': p['nice'],
'status': p['status'], 'status': p['status'],
} }

View File

@ -11,6 +11,7 @@
from glances.compat import nativestr from glances.compat import nativestr
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
import re
def secure_popen(cmd): def secure_popen(cmd):
@ -48,8 +49,9 @@ def __secure_popen(cmd):
p_last = None p_last = None
# Split by pipe '|' # Split by pipe '|'
for sub_cmd in cmd.split('|'): for sub_cmd in cmd.split('|'):
# Split by space ' ' # Split by space character, but do no split spaces within quotes (remove surrounding quotes, though)
sub_cmd_split = [i for i in sub_cmd.split(' ') if i] tmp_split = [_ for _ in list(filter(None, re.split(r'(\s+)|(".*?"+?)|(\'.*?\'+?)', sub_cmd))) if _ != ' ']
sub_cmd_split = [_[1:-1] if (_[0]==_[-1]=='"') or (_[0]==_[-1]=='\'') else _ for _ in tmp_split]
p = Popen(sub_cmd_split, shell=False, stdin=sub_cmd_stdin, stdout=PIPE, stderr=PIPE) p = Popen(sub_cmd_split, shell=False, stdin=sub_cmd_stdin, stdout=PIPE, stderr=PIPE)
if p_last is not None: if p_last is not None:
# Allow p_last to receive a SIGPIPE if p exits. # Allow p_last to receive a SIGPIPE if p exits.

View File

@ -118,7 +118,7 @@ class GlancesStats(object):
if args is not None: if args is not None:
# If the all key is set in the disable_plugin option then look in the enable_plugin option # If the all key is set in the disable_plugin option then look in the enable_plugin option
if getattr(args, 'disable_all', False): if getattr(args, 'disable_all', False):
logger.info('%s => %s', name, getattr(args, 'enable_' + name, False)) logger.debug('%s => %s', name, getattr(args, 'enable_' + name, False))
setattr(args, 'disable_' + name, not getattr(args, 'enable_' + name, False)) setattr(args, 'disable_' + name, not getattr(args, 'enable_' + name, False))
else: else:
setattr(args, 'disable_' + name, getattr(args, 'disable_' + name, False)) setattr(args, 'disable_' + name, getattr(args, 'disable_' + name, False))

View File

@ -22,6 +22,7 @@ potsdb
prometheus_client prometheus_client
pygal pygal
pymdstat pymdstat
pymongo; python_version >= "3.7"
pysnmp pysnmp
pySMART.smartx pySMART.smartx
python-dateutil python-dateutil
@ -32,5 +33,5 @@ six
sparklines sparklines
statsd statsd
wifi wifi
zeroconf==0.47.0; python_version < "3.7" zeroconf==0.47.1; python_version < "3.7"
zeroconf; python_version >= "3.7" zeroconf; python_version >= "3.7"

View File

@ -41,7 +41,16 @@ def get_data_files():
def get_install_requires(): def get_install_requires():
requires = ['psutil>=5.3.0', 'defusedxml', 'future', 'packaging'] requires = [
'psutil>=5.6.7',
'defusedxml',
'packaging',
'future; python_version < "3.0"',
'ujson<3; python_version < "3.0"',
'ujson<4; python_version >= "3.5" and python_version < "3.6"',
'ujson<5; python_version >= "3.6" and python_version < "3.7"',
'ujson>=5.4.0; python_version >= "3.7"',
]
if sys.platform.startswith('win'): if sys.platform.startswith('win'):
requires.append('bottle') requires.append('bottle')
requires.append('requests') requires.append('requests')
@ -52,12 +61,12 @@ def get_install_requires():
def get_install_extras_require(): def get_install_extras_require():
extras_require = { extras_require = {
'action': ['chevron'], 'action': ['chevron'],
'browser': ['zeroconf==0.47.0' if PY2 else 'zeroconf>=0.19.1'], 'browser': ['zeroconf==0.47.1' if PY2 else 'zeroconf>=0.19.1'],
'cloud': ['requests'], 'cloud': ['requests'],
'docker': ['docker>=2.0.0', 'python-dateutil', 'six'], 'docker': ['docker>=2.0.0', 'python-dateutil', 'six'],
'export': ['bernhard', 'cassandra-driver', 'couchdb', 'elasticsearch', 'export': ['bernhard', 'cassandra-driver', 'couchdb', 'elasticsearch',
'graphitesender', 'influxdb>=1.0.0', 'kafka-python', 'pika', 'graphitesender', 'influxdb>=1.0.0', 'kafka-python', 'pymongo',
'paho-mqtt', 'potsdb', 'prometheus_client', 'pyzmq', 'pika', 'paho-mqtt', 'potsdb', 'prometheus_client', 'pyzmq',
'statsd'], 'statsd'],
'folders': ['scandir'], # python_version<"3.5" 'folders': ['scandir'], # python_version<"3.5"
'graph': ['pygal'], 'graph': ['pygal'],