Commit e6018ceb authored by Stratos Psomadakis's avatar Stratos Psomadakis
Browse files

Merge branch 'feature-stats-vnc' into develop

parents 0f23c16c 64ec5678
......@@ -17,13 +17,13 @@ Synnefo-wide
* Integrate Pithos tests in continuous integration.
* Change astakosclient to accept AUTH_URL instead of BASE_URL
ASTAKOS_BASE_URL settings has been removed from Pithos and Cyclades
and has been replaced with ASTAKOS_AUTH_URL. Both Pithos and Cyclades
proxy the Astakos services under ASTAKOS_PROXY_PREFIX path.
ASTAKOS_PROXY_PREFIX by default has a value of '_astakos'.
More specifically, Astakos' identity service is proxied under
'_astakos/identity', Astakos' account service is under '_astakos/account'
and Astakos' ui service is under '_astakos/ui'.
ASTAKOS_BASE_URL settings has been removed from Pithos and Cyclades
and has been replaced with ASTAKOS_AUTH_URL. Both Pithos and Cyclades
proxy the Astakos services under ASTAKOS_PROXY_PREFIX path.
ASTAKOS_PROXY_PREFIX by default has a value of '_astakos'.
More specifically, Astakos' identity service is proxied under
'_astakos/identity', Astakos' account service is under '_astakos/account'
and Astakos' ui service is under '_astakos/ui'.
* Add 'mail_admins' handler to 'django.request' logger in order to send email
notifactions to users listed in 'ADMINS' setting about unhandled exceptions
......@@ -173,6 +173,14 @@ Cyclades
'service-export-cyclades'.
* Obsolete PUBLIC_USE_POOL setting, since Cyclades manages IP pool for all
type of networks.
* Encrypt / decrypt the instance id / hostname in the stats URL in
snf-cyclades-app and snf-stats-app, using the 'CYCLADES_STATS_SECRET_KEY'
and 'STATS_SECRET_KEY' respectively.
* Add support for snf-vncauthproxy-1.5 and the setting
'CYCLADES_VNCAUTHPROXY_OPTS', which configures the extra options / arguments
needed by the newer version of snf-vncauthproxy. Support for older versions
of snf-vncauthproxy has been dropped. See also the upgrade notes for Synnefo
and snf-vncauthproxy-1.5.
Pithos
------
......@@ -342,6 +350,7 @@ Cyclades
of the pool of Pithos backends that are used by plankton.
.. _Changelog-0.14:
v0.14
......
......@@ -5,6 +5,13 @@ Unified NEWS file for Synnefo versions >= 0.13
Since v0.13 all Synnefo components have been merged into a single repository.
v0.14next
=======
Released: UNRELEASED
* Support for snf-vncauthproxy-1.5 (drop support for older versions)
.. _NEWS-0.14.10:
v0.14.10
......
......@@ -527,7 +527,6 @@ the administrator has complete control on them without Cyclades knowing about
it. For example a VM migration to a different physical node is transparent
to Cyclades.
Working with Cyclades
---------------------
......@@ -999,6 +998,162 @@ pool are not used more than once.
Cyclades advanced operations
----------------------------
.. _admin-guide-stats:
VM stats collecting
~~~~~~~~~~~~~~~~~~~
snf-cyclades-gtools comes with a collectd plugin to collect CPU and network
stats for Ganeti VMs and an example collectd configuration. snf-stats-app is a
Django (snf-webproject) app that serves the VM stats graphs by reading the VM
stats (from RRD files) and serves graphs.
The snf-stats-app was originally written by `GRNET NOC <http://noc.grnet.gr>`_
as a WSGI Python app and was ported to a Synnefo (snf-webproject) app.
snf-stats-app configuration
```````````````````````````
The snf-stats-app node should have collectd installed. The collectd
configuration should enable the network plugin, assuming the server role, and
the RRD plugin / backend, to store the incoming stats. Your
``/etc/collectd/collectd.conf`` should look like:
.. code-block:: console
FQDNLookup true
LoadPlugin syslog
<Plugin syslog>
LogLevel info
</Plugin>
LoadPlugin network
LoadPlugin rrdtool
<Plugin network>
TimeToLive 128
<Listen "okeanos.io" "25826">
SecurityLevel "Sign"
AuthFile "/etc/collectd/passwd"
</Listen>
ReportStats false
MaxPacketSize 65535
</Plugin>
<Plugin rrdtool>
DataDir "/var/lib/collectd/rrd"
CacheTimeout 120
CacheFlush 900
WritesPerSecond 30
RandomTimeout 0
</Plugin>
Include "/etc/collectd/filters.conf"
Include "/etc/collectd/thresholds.conf"
An example collectd config file is provided in
``/usr/share/doc/snf-stats-app/examples/stats-colletcd.conf``.
The recommended deployment is to run snf-stats-app using gunicorn with an
Apache2 or nginx reverse proxy (using the same configuration as the other
Synnefo services / apps). An example gunicorn config file is provided in
``/usr/share/doc/snf-stats-app/examples/stats.gunicorn``.
Make sure to edit the settings under
``/etc/synnefo/20-snf-stats-app-settings.conf`` to match your deployment.
More specifically, you should change the ``STATS_BASE_URL`` setting (refer
to previous documentation on the BASE_URL settings used by the other Synnefo
services / apps) and the ``RRD_PREFIX`` and ``GRAPH_PREFIX`` settings.
You should also set the ``STATS_SECRET_KEY`` to a random string and make sure
it's the same at the ``CYCLADES_STATS_SECRET_KEY`` on the Cyclades host (see
below).
``RRD_PREFIX`` is the directory where collectd stores the RRD files. The
default setting matches the default RRD directory for the collectd RRDtool
plugin. In a more complex setup, the collectd daemon could run on a separate
host and export the RRD directory to the snf-stats-app node via e.g. NFS.
``GRAPH_PREFIX`` is the directory where collectd stores the resulting
stats graphs. You should create it manually, in case it doesn't exist.
.. code-block::
# mkdir /var/cache/snf-stats-app/
# chown www-data:wwwdata /var/cache/snf-stats-app/
The snf-stats-app will typically run as the ``www-data`` user. In that case,
make sure that the ``www-data`` user should have read access to the
``RRD_PREFIX`` directory and read / write access to the ``GRAPH_PREFIX``
directory.
snf-stats-app, based on the ``STATS_BASE_URL`` setting will export the
following URL 'endpoints`:
* CPU stats bar: ``STATS_BASE_URL``/v1.0/cpu-bar/<encrypted VM hostname>
* Network stats bar: ``STATS_BASE_URL``/v1.0/net-bar/<encrypted VM hostname>
* CPU stats daily graph: ``STATS_BASE_URL``/v1.0/cpu-ts/<encrypted VM hostname>
* Network stats daily graph: ``STATS_BASE_URL``/v1.0/net-ts/<encrypted VM hostname>
* CPU stats weekly graph: ``STATS_BASE_URL``/v1.0/cpu-ts-w/<encrypted VM hostname>
* Network stats weekly graph: ``STATS_BASE_URL``/v1.0/net-ts-w/<encrypted VM hostname>
You can verify that these endpoints are exported by issuing:
.. code-block::
# snf-manage show_urls
snf-cyclades-gtools configuration
`````````````````````````````````
To enable VM stats collecting, you will need to:
* Install collectd on the every Ganeti (VM-capable) node.
* Enable the Ganeti stats plugin in your collectd configuration. This can be
achived by either copying the example collectd conf file that comes with
snf-cyclades-gtools
(``/usr/share/doc/snf-cyclades-gtools/examples/ganeti-stats-collectd.conf``)
or by adding the following line to your existing (or default) collectd
conf file:
Include /etc/collectd/ganeti-stats.conf
In the latter case, make sure to configure collectd to send the collected
stats to your collectd server (via the network plugin). For more details on
how to do this, check the collectd example config file provided by the
package and the collectd documentation.
snf-cyclades-app configuration
``````````````````````````````
At this point, stats collecting should be enabled and working. You can check
that everything is ok by checking the contents of ``/var/lib/collectd/rrd/``
directory (it will gradually get populated with directories containing RRD
files / stats for every Synnefo instances).
You should also check that gunicorn and Apache2 are configured correctly by
accessing the graph URLs for a VM (whose stats have been populated in
``/var/lib/collectd/rrd``).
Cyclades uses the ``CYCLADES_STATS_SECRET_KEY`` setting in
``20-snf-cyclades-app`` to encrypt the instance hostname in the stats graph
URL. This settings should be set to a random value and match the
``STATS_SECRET_KEY`` on the Stats host.
Cyclades (snf-cyclades-app) fetches the stat graphs for VMs based on four
settings in ``20-snf-cyclades-app-api.conf``. The settings are:
* CPU_BAR_GRAPH_URL = 'https://stats.host/stats/v1.0/cpu-bar/%s'
* CPU_TIMESERIES_GRAPH_URL = 'https://stats.host/stats/v1.0/cpu-ts/%s'
* NET_BAR_GRAPH_URL = 'https://stats.host/stats/v1.0/net-bar/%s'
* NET_TIMESERIES_GRAPH_URL = 'https://stats.host/stats/v1.0/net-ts/%s'
Make sure that you change this settings to match your ``STATS_BASE_URL``
(and generally the Apache2 / gunicorn deployment on your stats host).
Cyclades will pass these URLs to the Cyclades UI and the user's browser will
fetch them when needed.
Reconciliation mechanism
~~~~~~~~~~~~~~~~~~~~~~~~
......
......@@ -131,7 +131,7 @@ They are also available from our apt repository: ``apt.dev.grnet.gr``
* `snf-cyclades-app <http://www.synnefo.org/docs/snf-cyclades-app/latest/index.html>`_
* `snf-cyclades-gtools <http://www.synnefo.org/docs/snf-cyclades-gtools/latest/index.html>`_
* `astakosclient <http://www.synnefo.org/docs/astakosclient/latest/index.html>`_
* `snf-vncauthproxy <https://code.grnet.gr/projects/vncauthproxy>`_
* `snf-vncauthproxy <https://www.synnefo.org/docs/snf-vncauthproxy/latest/index.html>`_
* `snf-image <http://www.synnefo.org/docs/snf-image/latest/index.html/>`_
* `snf-image-creator <http://www.synnefo.org/docs/snf-image-creator/latest/index.html>`_
* `snf-occi <http://www.synnefo.org/docs/snf-occi/latest/index.html>`_
......
......@@ -2127,6 +2127,12 @@ skipped.
node2 # snf-manage reconcile-resources-pithos --fix
node1 # snf-manage reconcile-resources-cyclades --fix
VM stats configuration
----------------------
Please refer to the documentation in the :ref:`admin guide <admin-guide-stats>`
for deploying and configuring snf-stats-app and collectd.
If all the above return successfully, then you have finished with the Cyclades
installation and setup.
......
......@@ -160,6 +160,83 @@ setting will have the value of
For Pithos service we have to change the ``20-snf-pithos-app-settings.conf``
file in the same way as above.
2.4 Upgrade vncauthproxy and configure snf-cyclades-app
-------------------------------------------------------
Synnefo v0.15 adds support for snf-vncauthproxy >= 1.5 and drops support for
older versions. You will have to upgrade snf-vncauthproxy to v1.5 and configure
the authentication (users) file (``/var/lib/vncauthproxy/users``).
In case you're upgrading from an older snf-vncauthproxy version or it's the
first time you're installing snf-vncauthproxy, you will prompted to configure
a vncauthproxy user (see below for more information on user management).
To manage the authentication file, you can use the vncauthproxy-passwd tool,
to easily add, update and delete users
To add a user:
.. code-block:: console
# vncauthproxy-passwd /var/lib/vncauthproxy/users synnefo
You will be prompted for a password.
You should also configure the new ``CYCLADES_VNCAUTHPROXY_OPTS`` setting in
``snf-cyclades-app``, to provide the user and password configured for
``Synnefo`` in the vncauthproxy authentication file and enable SSL support if
snf-vncauthproxy is configured to run with SSL enabled for the control socket.
.. warning:: The vncauthproxy daemon requires a restart for the changes in the
authentication file to take effect.
.. warning:: If you fail to provide snf-vncauthproxy with a valid
authentication file, or in case the configuration of vncauthproxy and the
vncauthproxy snf-cyclades-app settings don't match (ie not having SSL enabled
on both), VNC console access will not be functional.
Finally, snf-vncauthproxy-1.5 adds a dedicated user and group to be used by the
vncauthproxy daemon. The Debian default file has changed accordingly (``CHUID``
option in ``/etc/default/vncauthproxy``). The Debian default file now also
includes a ``DAEMON_OPTS`` variable which is used to pass any necessary / extra
options to the vncauthproxy daemon. In case you're ugprading from an older
version of vncauthproxy, you should make sure to 'merge' the new default file
with the older one.
Check the `documentation
<http://www.synnefo.org/docs/snf-vncauthproxy/latest/index.html>`_ of
snf-vncauthproxy for more information on upgrading to version 1.5.
2.5 Stats configuration
-----------------------
snf-cyclades-gtools comes with a collectd plugin to collect CPU and network
stats for Ganeti VMs and an example collectd configuration. snf-stats-app is a
Django (snf-webproject) app that serves the VM stats graphsmm by reading the VM
stats (from RRD files) and serves graphs.
To enable / deploy VM stats collecting and snf-stats-app see the relevant
documentation in the :ref:`admin guide <admin-guide-stats>`.
If you were using collectd to collect VM stats on Debian squeeze and you are
upgrading to Wheezy, you will need to upgrade your RRD files. Follow the
instructions on the collectd v4-to-v5 migration `guide
<https://collectd.org/wiki/index.php/V4_to_v5_migration_guide>`_.
You will proabably just need to run the `migration script
<https://collectd.org/wiki/index.php/V4_to_v5_migration_guide#Migration_script>`_
provided.
If you were using a previous version of snf-stats-app, you should also make
sure to set the ``STATS_BASE_URL`` setting in ``20-snf-stats-app-settings.conf``
to match your deployment and change the graph URL settings in
``20-snf-cyclades-app-api.conf`` accordingly.
v0.15 has also introduced the ``CYCLADES_STATS_SECRET_KEY`` and
``STATS_SECRET_KEY`` settings. ``CYCLADES_STATS_SECRET_KEY`` in
``20-snf-cyclades-app-api.conf`` is used by Cyclades to encrypt the instance id
/ hostname in the URLs serving the VM stats. You should set it to a random
value / string and make sure that it's the same as the ``STATS_SECRET_KEY``
setting (used to decrypt the instance hostname) in
``20-snf-stats-settings.conf`` on your Stats host.
3. Create floating IP pools
===========================
......
......@@ -85,13 +85,17 @@
#BACKEND_PER_USER = {}
#
#
## Encryption key for the instance hostname in the stat graphs URLs. Set it to
## a random string and update the STATS_SECRET_KEY setting in the snf-stats-app
## host (20-snf-stats-app-settings.conf) accordingly.
#CYCLADES_STATS_SECRET_KEY = "secret key"
#
## URL templates for the stat graphs.
## The API implementation replaces '%s' with the encrypted backend id.
## FIXME: For now we do not encrypt the backend id.
#CPU_BAR_GRAPH_URL = 'http://stats.synnefo.org/%s/cpu-bar.png'
#CPU_TIMESERIES_GRAPH_URL = 'http://stats.synnefo.org/%s/cpu-ts.png'
#NET_BAR_GRAPH_URL = 'http://stats.synnefo.org/%s/net-bar.png'
#NET_TIMESERIES_GRAPH_URL = 'http://stats.synnefo.org/%s/net-ts.png'
#CPU_BAR_GRAPH_URL = 'http://stats.example.synnefo.org/stats/v1.0/cpu-bar/%s'
#CPU_TIMESERIES_GRAPH_URL = 'http://stats.example.synnefo.org/stats/v1.0/cpu-ts/%s'
#NET_BAR_GRAPH_URL = 'http://stats.example.synnefo.org/net-bar/stats/v1.0/%s'
#NET_TIMESERIES_GRAPH_URL = 'http://stats.example.synnefo.org/stats/v1.0/net-ts/%s'
#
## Recommended refresh period for server stats
#STATS_REFRESH_PERIOD = 60
......@@ -149,3 +153,23 @@
## ("gate.example.synnefo.org", 61000 + server_id),
##}
#CYCLADES_PORT_FORWARDING = {}
## Extra configuration options required for snf-vncauthproxy (>=1.5)
#CYCLADES_VNCAUTHPROXY_OPTS = {
# # These values are required for VNC console support. They should match a
# # user / password configured in the snf-vncauthproxy authentication / users
# # file (/var/lib/vncauthproxy/users).
# 'auth_user': 'synnefo',
# 'auth_password': 'secret_password',
# # server_address and server_port should reflect the --listen-address and
# # --listen-port options passed to the vncauthproxy daemon
# 'server_address': '127.0.0.1',
# 'server_port': 24999,
# # Set to True to enable SSL support on the control socket.
# 'enable_ssl': False,
# # If you enabled SSL support for snf-vncauthproxy you can optionally
# # provide a path to a CA file and enable strict checkfing for the server
# # certficiate.
# 'ca_cert': None,
# 'strict': False,
#}
......@@ -68,7 +68,7 @@ INSTALL_REQUIRES = [
'puka',
'python-daemon>=1.5.5, <1.6',
'snf-common',
'vncauthproxy>=1.2',
'vncauthproxy>=1.5',
'snf-pithos-backend',
'lockfile>=0.8, <0.9',
'ipaddr',
......
......@@ -687,8 +687,7 @@ def server_stats(request, server_id):
log.debug('server_stats %s', server_id)
vm = util.get_vm(server_id, request.user_uniq)
#secret = util.encrypt(vm.backend_vm_id)
secret = vm.backend_vm_id # XXX disable backend id encryption
secret = util.stats_encrypt(vm.backend_vm_id)
stats = {
'serverRef': vm.id,
......
......@@ -31,7 +31,8 @@
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from base64 import b64encode, b64decode
from base64 import urlsafe_b64encode, b64decode
from urllib import quote
from hashlib import sha256
from logging import getLogger
from random import choice
......@@ -118,13 +119,13 @@ def zeropad(s):
return s + '\x00' * npad
def encrypt(plaintext):
def stats_encrypt(plaintext):
# Make sure key is 32 bytes long
key = sha256(settings.SECRET_KEY).digest()
key = sha256(settings.CYCLADES_STATS_SECRET_KEY).digest()
aes = AES.new(key)
enc = aes.encrypt(zeropad(plaintext))
return b64encode(enc)
return quote(urlsafe_b64encode(enc))
def get_vm(server_id, user_id, for_update=False, non_deleted=False,
......
......@@ -84,13 +84,17 @@ DEFAULT_FIREWALL_PROFILE = 'DISABLED'
BACKEND_PER_USER = {}
# Encryption key for the instance hostname in the stat graphs URLs. Set it to
# a random string and update the STATS_SECRET_KEY setting in the snf-stats-app
# host (20-snf-stats-app-settings.conf) accordingly.
CYCLADES_STATS_SECRET_KEY = "secret_key"
# URL templates for the stat graphs.
# The API implementation replaces '%s' with the encrypted backend id.
# FIXME: For now we do not encrypt the backend id.
CPU_BAR_GRAPH_URL = 'http://stats.synnefo.org/%s/cpu-bar.png'
CPU_TIMESERIES_GRAPH_URL = 'http://stats.synnefo.org/%s/cpu-ts.png'
NET_BAR_GRAPH_URL = 'http://stats.synnefo.org/%s/net-bar.png'
NET_TIMESERIES_GRAPH_URL = 'http://stats.synnefo.org/%s/net-ts.png'
CPU_BAR_GRAPH_URL = 'http://stats.example.synnefo.org/stats/v1.0/cpu-bar/%s'
CPU_TIMESERIES_GRAPH_URL = 'http://stats.example.synnefo.org/stats/v1.0/cpu-ts/%s'
NET_BAR_GRAPH_URL = 'http://stats.example.synnefo.org/stats/v1.0/net-bar/%s'
NET_TIMESERIES_GRAPH_URL = 'http://stats.example.synnefo.org/stats/v1.0/net-ts/%s'
# Recommended refresh period for server stats
STATS_REFRESH_PERIOD = 60
......@@ -146,3 +150,23 @@ CYCLADES_SERVERS_FQDN = 'snf-%(id)s.vm.example.synnefo.org'
# ("gate.example.synnefo.org", 61000 + server_id),
#}
CYCLADES_PORT_FORWARDING = {}
# Extra configuration options required for snf-vncauthproxy (>=1.5)
CYCLADES_VNCAUTHPROXY_OPTS = {
# These values are required for VNC console support. They should match a
# user / password configured in the snf-vncauthproxy authentication / users
# file (/var/lib/vncauthproxy/users).
'auth_user': 'synnefo',
'auth_password': 'secret_password',
# server_address and server_port should reflect the --listen-address and
# --listen-port options passed to the vncauthproxy daemon
'server_address': '127.0.0.1',
'server_port': 24999,
# Set to True to enable SSL support on the control socket.
'enable_ssl': False,
# If you enabled SSL support for snf-vncauthproxy you can optionally
# provide a path to a CA file and enable strict checkfing for the server
# certficiate.
'ca_cert': None,
'strict': False,
}
......@@ -392,7 +392,9 @@ def console(vm, console_type):
if settings.TEST:
fwd = {'source_port': 1234, 'status': 'OK'}
else:
fwd = request_vnc_forwarding(sport, daddr, dport, password)
vnc_extra_opts = settings.CYCLADES_VNCAUTHPROXY_OPTS
fwd = request_vnc_forwarding(sport, daddr, dport, password,
**vnc_extra_opts)
if fwd['status'] != "OK":
raise faults.ServiceUnavailable('vncauthproxy returned error status')
......
......@@ -5,5 +5,6 @@
ModulePath "/usr/lib/snf-cyclades-gtools/collectd/"
LogTraces true
Interactive false
Import "ganeti-stats"
Import "ganeti-cpustats"
Import "ganeti-netstats"
</Plugin>
......@@ -25,7 +25,8 @@ LoadPlugin network
ModulePath "/usr/lib/snf-cyclades-gtools/collectd/"
LogTraces true
Interactive false
Import "ganeti-stats"
Import "ganeti-cpustats"
Import "ganeti-netstats"
</Plugin>
Include "/etc/collectd/filters.conf"
......
#!/usr/bin/env python
import os
import collectd
from glob import glob
def get_vcpus(pid):
"""Get a KVM instance vCPU count by looking at its fd's"""
vcpus = 0
for fd in glob("/proc/%d/fd/*" % pid):
# XXX: sad but trueeeeeeeeeeee
if os.readlink(fd) == "anon_inode:kvm-vcpu":
vcpus += 1
return vcpus
def cpustats(data=None):
for file in glob("/var/run/ganeti/kvm-hypervisor/pid/*"):
instance = os.path.basename(file)
try:
pid = int(open(file, "r").read())
proc = open("/proc/%d/stat" % pid, "r")
cputime = [int(proc.readline().split()[42])]
except EnvironmentError:
continue
vcpus = get_vcpus(pid)
proc.close()
vl = collectd.Values(type="derive")
vl.host = instance
vl.plugin = "cpu"
vl.type = "virt_cpu_total"
total = sum(cputime) * 100 / (vcpus * os.sysconf("SC_CLK_TCK"))
vl.dispatch(values=[total])
collectd.register_read(cpustats)
# vim: set ts=4 sts=4 et sw=4 :
......@@ -3,8 +3,6 @@
import os
import collectd
from hashlib import md5
from glob import glob
......@@ -20,21 +18,6 @@ def read_int(file):
return val
def anonymize_hostname(hostname):
#return md5(hostname).hexdigest()
return hostname
def get_vcpus(pid):
"""Get a KVM instance vCPU count by looking at its fd's"""
vcpus = 0
for fd in glob("/proc/%d/fd/*" % pid):
# XXX: sad but trueeeeeeeeeeee
if os.readlink(fd) == "anon_inode:kvm-vcpu":
vcpus += 1
return vcpus
def netstats(data=None):
for dir in glob("/var/run/ganeti/kvm-hypervisor/nic/*"):
if not os.path.isdir(dir):
......@@ -52,38 +35,19 @@ def netstats(data=None):
if not os.path.isdir("/sys/class/net/%s" % iface):
continue
bytes_in = read_int("/sys/class/net/%s/statistics/rx_bytes" % iface)
bytes_out = read_int("/sys/class/net/%s/statistics/tx_bytes" % iface)
vl = collectd.Values(type="counter")
vl.host = anonymize_hostname(hostname)
bytes_in = read_int("/sys/class/net/%s/statistics/rx_bytes"
% iface)
bytes_out = read_int("/sys/class/net/%s/statistics/tx_bytes"
% iface)
vl = collectd.Values(type="derive")
vl.host = hostname
vl.plugin = "interface"
vl.type = "if_octets"
vl.type_instance = "eth%d" % idx
vl.dispatch(values=[bytes_out, bytes_in])
def cpustats(data=None):
for file in glob("/var/run/ganeti/kvm-hypervisor/pid/*"):
instance = os.path.basename(file)
try:
pid = int(open(file, "r").read())
proc = open("/proc/%d/stat" % pid, "r")
cputime = [int(proc.readline().split()[42])]
except EnvironmentError:
continue