First sprint for the outdated function

pull/893/head
Nicolargo 2016-05-13 18:23:42 +02:00
parent fd83a9f92a
commit 2aab7db010
3 changed files with 172 additions and 0 deletions

View File

@ -71,6 +71,10 @@ LOGGING_CFG = {
'handlers': ['file'],
'level': 'INFO'
},
'requests': {
'handlers': ['file', 'console'],
'level': 'ERROR',
},
'elasticsearch': {
'handlers': ['file', 'console'],
'level': 'ERROR',

159
glances/outdated.py Normal file
View File

@ -0,0 +1,159 @@
# -*- coding: utf-8 -*-
#
# This file is part of Glances.
#
# Copyright (C) 2016 Nicolargo <nicolas@nicolargo.com>
#
# Glances is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Glances 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""Manage Glances update."""
from datetime import datetime, timedelta
from distutils.version import LooseVersion
import threading
import json
import pickle
import os
try:
import requests
except ImportError:
outdated_tag = False
else:
outdated_tag = True
from glances import __version__, __appname__
from glances.globals import BSD, LINUX, OSX, WINDOWS
from glances.logger import logger
class Outdated(object):
"""
This class aims at providing methods to warn the user when a new Glances
version is available on the Pypi repository (https://pypi.python.org/pypi/Glances/).
"""
PYPI_API_URL = 'https://pypi.python.org/pypi/Glances/json'
max_refresh_date = timedelta(days=7)
def __init__(self, args, config):
"""Init the Outdated class"""
self.args = args
self.config = config
# Set default value...
self.data = {
'installed_version': __version__,
'latest_version': '0.0',
'refresh_date': None
}
# ... and update
self.get_pypi_version()
def installed_version(self):
return self.data['installed_version']
def latest_version(self):
return self.data['latest_version']
def refresh_date(self):
return self.data['refresh_date']
def get_pypi_version(self):
"""Wrapper to get the latest Pypi version (async)
The data are stored in a cached file
Only update online once a week
"""
# If the cached file exist, read-it
cached_data = self._load_cache()
if outdated_tag and cached_data == {}:
# Update needed
# Update and save the cache
thread = threading.Thread(target=self._update_pypi_version)
thread.start()
else:
# Update not needed
self.data['latest_version'] = cached_data['latest_version']
logger.debug("Get the Glances version from the cache file")
def _load_cache(self):
"""Load cache file and return cached data"""
# If the cached file exist, read-it
cached_data = {}
try:
with open(os.path.join(self._cache_path(), 'glances-version.db'), 'rb') as f:
cached_data = pickle.load(f)
except IOError as e:
logger.debug("Can not read the version cache file ({0})".format(e))
else:
logger.debug("Read the version cache file")
if cached_data['installed_version'] != self.installed_version() or \
datetime.now() - cached_data['refresh_date'] > self.max_refresh_date:
# Reset the cache if:
# - the installed version is different
# - the refresh_date is > max_refresh_date
cached_data = {}
return cached_data
def _save_cache(self):
"""Save data to a file"""
# If the cached file exist, read-it
try:
with open(os.path.join(self._cache_path(), 'glances-version.db'), 'wb') as f:
pickle.dump(self.data, f)
except IOError:
return False
return True
def _cache_path(self):
"""Return the cached file path"""
if LINUX or BSD:
return os.path.join(os.environ.get('XDG_CONFIG_HOME') or
os.path.expanduser('~/.config'),
__appname__)
elif OSX:
return os.path.join(os.path.expanduser('~/Library/Application Support/'),
__appname__)
elif WINDOWS:
return os.path.join(os.environ.get('APPDATA'), __appname__)
def _update_pypi_version(self):
"""Get the latest Pypi version (as a string) via the Restful JSON API"""
# Get the Nginx status
logger.debug("Get latest Glances version from the Pypi Restfull API ({0})".format(self.PYPI_API_URL))
try:
res = requests.get(self.PYPI_API_URL)
except Exception as e:
logger.debug("Can not get the Glances version from the Pypi Restfull API ({0})".format(e))
else:
if res.ok:
# Update data
self.data['latest_version'] = json.loads(res.text)['info']['version']
self.data['refresh_date'] = datetime.now()
# Save result to the cache file
self._save_cache()
logger.debug("Save Glances version to the cache file")
else:
logger.debug("Can not get the Glances version from the Pypi Restfull API ({0})".format(res.reason))
return self.data
def is_outdated(self):
"""Return True if a new version is available"""
if not outdated_tag:
logger.debug("Python Request lib is not installed. Can not get last Glances version on Pypi.")
return False
logger.debug("Check Glances version (installed: {0} / latest: {1})".format(self.installed_version(), self.latest_version()))
return LooseVersion(self.latest_version()) > LooseVersion(self.installed_version())

View File

@ -26,6 +26,7 @@ from glances.logger import logger
from glances.processes import glances_processes
from glances.stats import GlancesStats
from glances.outputs.glances_curses import GlancesCursesStandalone
from glances.outdated import Outdated
class GlancesStandalone(object):
@ -77,6 +78,9 @@ class GlancesStandalone(object):
# Init screen
self.screen = GlancesCursesStandalone(config=config, args=args)
# Check the latest Glances version
self.outdated = Outdated(config=config, args=args)
@property
def quiet(self):
return self._quiet
@ -115,3 +119,8 @@ class GlancesStandalone(object):
# Exit from export modules
self.stats.end()
# Check Glances version versus Pypi one
if self.outdated.is_outdated():
print("You are using Glances version {0}, however version {1} is available.".format(self.outdated.installed_version(), self.outdated.latest_version()))
print("You should consider upgrading using: pip install --upgrade glances")