diff --git a/psdash/net.py b/psdash/net.py index 7d75abd..b5480a6 100644 --- a/psdash/net.py +++ b/psdash/net.py @@ -19,7 +19,7 @@ def _get_net_io_counters(self): counters = psutil.net_io_counters(pernic=self.pernic) res = {} - for name, io in counters.iteritems(): + for name, io in counters.items(): res[name] = io._asdict() res[name].update({'tx_per_sec': 0, 'rx_per_sec': 0}) @@ -43,7 +43,7 @@ def update(self): if not time_delta: return counters - for name, io in counters.iteritems(): + for name, io in counters.items(): last_io = self.last_req.get(name) if not last_io: continue @@ -70,7 +70,7 @@ def get_interface_addresses(): ifaces = netifaces.interfaces() for iface in ifaces: addrs = netifaces.ifaddresses(iface) - families = addrs.keys() + families = list(addrs.keys()) # put IPv4 to the end so it lists as the main iface address if netifaces.AF_INET in families: diff --git a/psdash/node.py b/psdash/node.py index 40f1aff..8db4356 100644 --- a/psdash/node.py +++ b/psdash/node.py @@ -5,7 +5,7 @@ import psutil import socket import time -import zerorpc +#import zerorpc from psdash.log import Logs from psdash.helpers import socket_families, socket_types from psdash.net import get_interface_addresses, NetIOCounters @@ -76,10 +76,11 @@ def get_sysinfo(self): 'uptime': uptime, 'hostname': socket.gethostname(), 'os': platform.platform(), - 'load_avg': os.getloadavg(), + 'load_avg': (0.0, 0.0, 0.0), 'num_cpus': psutil.cpu_count() } - + if getattr(os, "getloadavg", None) != None: + sysinfo['load_avg'] = os.getloadavg() return sysinfo def get_memory(self): @@ -122,7 +123,7 @@ def get_disks(self, all_partitions=False): return disks def get_disks_counters(self, perdisk=True): - return dict((dev, c._asdict()) for dev, c in psutil.disk_io_counters(perdisk=perdisk).iteritems()) + return dict((dev, c._asdict()) for dev, c in psutil.disk_io_counters(perdisk=perdisk).items()) def get_users(self): return [u._asdict() for u in psutil.users()] @@ -325,7 +326,7 @@ def get_connections(self, filters=None): 'state': c.status } - for k, v in filters.iteritems(): + for k, v in filters.items(): if v and conn.get(k) != v: break else: diff --git a/psdash/run.py b/psdash/run.py index 32e54bb..1e97fff 100644 --- a/psdash/run.py +++ b/psdash/run.py @@ -1,17 +1,31 @@ -import gevent -from gevent.monkey import patch_all -patch_all() -from gevent.pywsgi import WSGIServer +# define Python 3 compatible eventloop API + +class eventloop(object): + call_later = None + +try: + import gevent + from gevent.monkey import patch_all + patch_all() + + from gevent.pywsgi import WSGIServer + eventloop.call_later = gevent.spawn_later +except ImportError: + gevent = False + import asyncio + eventloop = asyncio.get_event_loop() + + import locale import argparse import logging import socket import urllib -import urllib2 +#import urllib2 from logging import getLogger from flask import Flask -import zerorpc +#import zerorpc from psdash import __version__ from psdash.node import LocalNode, RemoteNode from psdash.web import fromtimestamp @@ -106,7 +120,7 @@ def _get_args(cls, args): def _load_args_config(self, args): config = {} - for k, v in vars(self._get_args(args)).iteritems(): + for k, v in vars(self._get_args(args)).items(): if v: key = 'PSDASH_%s' % k.upper() if k != 'debug' else 'DEBUG' config[key] = v @@ -189,15 +203,15 @@ def _setup_logging(self): def _setup_workers(self): net_io_interval = self.app.config.get('PSDASH_NET_IO_COUNTER_INTERVAL', self.DEFAULT_NET_IO_COUNTER_INTERVAL) - gevent.spawn_later(net_io_interval, self._net_io_counters_worker, net_io_interval) + eventloop.call_later(net_io_interval, self._net_io_counters_worker, net_io_interval) if 'PSDASH_LOGS' in self.app.config: logs_interval = self.app.config.get('PSDASH_LOGS_INTERVAL', self.DEFAULT_LOG_INTERVAL) - gevent.spawn_later(logs_interval, self._logs_worker, logs_interval) + eventloop.call_later(logs_interval, self._logs_worker, logs_interval) if self.app.config.get('PSDASH_AGENT'): register_interval = self.app.config.get('PSDASH_REGISTER_INTERVAL', self.DEFAULT_REGISTER_INTERVAL) - gevent.spawn_later(register_interval, self._register_agent_worker, register_interval) + eventloop.call_later(register_interval, self._register_agent_worker, register_interval) def _setup_locale(self): # This set locale to the user default (usually controlled by the LANG env var) @@ -276,16 +290,20 @@ def _run_web(self): 'certfile': self.app.config.get('PSDASH_HTTPS_CERTFILE') } - listen_to = ( - self.app.config.get('PSDASH_BIND_HOST', self.DEFAULT_BIND_HOST), - self.app.config.get('PSDASH_PORT', self.DEFAULT_PORT) - ) - self.server = WSGIServer( - listen_to, - application=self.app, - log=log, - **ssl_args - ) + host = self.app.config.get('PSDASH_BIND_HOST', self.DEFAULT_BIND_HOST) + port = self.app.config.get('PSDASH_PORT', self.DEFAULT_PORT) + if gevent: + listen_to = (host, port) + self.server = WSGIServer( + listen_to, + application=self.app, + log=log, + **ssl_args + ) + else: + from wsgiref.simple_server import make_server + self.server = make_server(host, port, self.app) + print("Serving with wsgiref on http://%s:%s ..." % (host, port)) self.server.serve_forever() def run(self): diff --git a/psdash/templates/base.html b/psdash/templates/base.html index 1967d64..350f976 100644 --- a/psdash/templates/base.html +++ b/psdash/templates/base.html @@ -39,7 +39,7 @@ diff --git a/psdash/templates/disks.html b/psdash/templates/disks.html index f6f1253..36e5331 100644 --- a/psdash/templates/disks.html +++ b/psdash/templates/disks.html @@ -22,7 +22,7 @@ {% for d in disks %} {{ d.device }} - {{ d.mountpoint.decode("utf-8") }} + {{ d.mountpoint }} {{ d.type }} {{ d.options }} {{ d.space_total|filesizeformat }} diff --git a/psdash/templates/index.html b/psdash/templates/index.html index ca9c80a..65740da 100644 --- a/psdash/templates/index.html +++ b/psdash/templates/index.html @@ -80,7 +80,7 @@ {% for ni in net_interfaces %} - {{ ni.name.decode("utf-8") }} + {{ ni.name }} {{ ni.ip }} {{ ni.send_rate|default(0)|filesizeformat }} {{ ni.recv_rate|default(0)|filesizeformat }} @@ -109,7 +109,7 @@ {% for d in disks %} {{ d.device }} - {{ d.mountpoint.decode("utf-8") }} + {{ d.mountpoint }} {{ d.space_total|filesizeformat }} {{ d.space_used|filesizeformat }} ({{ d.space_used_percent }} %) {{ d.space_free|filesizeformat }} @@ -164,7 +164,7 @@ {% for u in users %} - {{ u.name.decode("utf-8") }} + {{ u.name }} {{ u.started|fromtimestamp }} {{ u.host }} diff --git a/psdash/templates/network.html b/psdash/templates/network.html index 2155f27..876f5a4 100644 --- a/psdash/templates/network.html +++ b/psdash/templates/network.html @@ -68,7 +68,7 @@ @@ -76,7 +76,7 @@ diff --git a/psdash/templates/process/environment.html b/psdash/templates/process/environment.html index 4d3413a..33ee1b8 100644 --- a/psdash/templates/process/environment.html +++ b/psdash/templates/process/environment.html @@ -8,7 +8,7 @@ - {% for var, value in process_environ.iteritems() %} + {% for var, value in process_environ.items() %} {{ var.decode("utf-8") }} {{ value.decode("utf-8") }} diff --git a/psdash/web.py b/psdash/web.py index 2ba70ce..8ef1fae 100755 --- a/psdash/web.py +++ b/psdash/web.py @@ -37,12 +37,13 @@ def inject_nodes(): @webapp.context_processor def inject_header_data(): + # automatic variables for all Jinja2 templates sysinfo = current_service.get_sysinfo() uptime = timedelta(seconds=sysinfo['uptime']) uptime = str(uptime).split('.')[0] return { - 'os': sysinfo['os'].decode('utf-8'), - 'hostname': sysinfo['hostname'].decode('utf-8'), + 'os': sysinfo['os'], + 'hostname': sysinfo['hostname'], 'uptime': uptime } @@ -107,7 +108,7 @@ def access_denied(e): def index(): sysinfo = current_service.get_sysinfo() - netifs = current_service.get_network_interfaces().values() + netifs = list(current_service.get_network_interfaces().values()) netifs.sort(key=lambda x: x.get('bytes_sent'), reverse=True) data = { @@ -188,7 +189,7 @@ def process(pid, section): whitelist = current_app.config.get('PSDASH_ENVIRON_WHITELIST') if whitelist: penviron = dict((k, v if k in whitelist else '*hidden by whitelist*') - for k, v in penviron.iteritems()) + for k, v in penviron.items()) context['process_environ'] = penviron elif section == 'threads': @@ -212,7 +213,7 @@ def process(pid, section): @webapp.route('/network') def view_networks(): - netifs = current_service.get_network_interfaces().values() + netifs = list(current_service.get_network_interfaces().values()) netifs.sort(key=lambda x: x.get('bytes_sent'), reverse=True) # {'key', 'default_value'} @@ -224,7 +225,7 @@ def view_networks(): 'state': 'LISTEN' } - form_values = dict((k, request.args.get(k, default_val)) for k, default_val in form_keys.iteritems()) + form_values = dict((k, request.args.get(k, default_val)) for k, default_val in form_keys.items()) for k in ('local_addr', 'remote_addr'): val = request.args.get(k, '') @@ -262,7 +263,7 @@ def view_networks(): @webapp.route('/disks') def view_disks(): disks = current_service.get_disks(all_partitions=True) - io_counters = current_service.get_disks_counters().items() + io_counters = list(current_service.get_disks_counters().items()) io_counters.sort(key=lambda x: x[1]['read_count'], reverse=True) return render_template( 'disks.html', @@ -276,7 +277,7 @@ def view_disks(): @webapp.route('/logs') def view_logs(): available_logs = current_service.get_logs() - available_logs.sort(cmp=lambda x1, x2: locale.strcoll(x1['path'], x2['path'])) + available_logs.sort(key=locale.strxfrm) return render_template( 'logs.html',