Initial backend XOS APIs for XOS operator ceilometer dashboard
diff --git a/xos/configurations/cord/install_ceilometer_patch.sh b/xos/configurations/cord/install_ceilometer_patch.sh
index 279e07c..d6b4056 100755
--- a/xos/configurations/cord/install_ceilometer_patch.sh
+++ b/xos/configurations/cord/install_ceilometer_patch.sh
@@ -11,7 +11,9 @@
 echo "Copying the ceilometer patch files to /usr/lib/python2.7/dist-packages/ceilometer"
 tar -xzf openstack_ceilometer_patch.tar.gz
 sudo mv ceilometer/network/ext_services /usr/lib/python2.7/dist-packages/ceilometer/network/
-sudo mv ceilometer/network/statistics /usr/lib/python2.7/dist-packages/ceilometer/network/
+sudo mv ceilometer/network/statistics/onos /usr/lib/python2.7/dist-packages/ceilometer/network/statistics/
+sudo mv /usr/lib/python2.7/dist-packages/ceilometer/network/statistics/__init__.py /usr/lib/python2.7/dist-packages/ceilometer/network/statistics/orig_init.orig_py
+sudo mv ceilometer/network/statistics/__init__.py /usr/lib/python2.7/dist-packages/ceilometer/network/statistics/
 sudo mv ceilometer-2015.1.1.egg-info/entry_points.txt /usr/lib/python2.7/dist-packages/ceilometer-*egg-info/
 sudo mv pipeline.yaml /etc/ceilometer/
 echo "Restarting ceilometer-agent-notification"
diff --git a/xos/configurations/cord/openstack_ceilometer_patch.tar.gz b/xos/configurations/cord/openstack_ceilometer_patch.tar.gz
index dc1852a..6a6ffa7 100644
--- a/xos/configurations/cord/openstack_ceilometer_patch.tar.gz
+++ b/xos/configurations/cord/openstack_ceilometer_patch.tar.gz
Binary files differ
diff --git a/xos/core/xoslib/methods/ceilometerview.py b/xos/core/xoslib/methods/ceilometerview.py
new file mode 100644
index 0000000..a453524
--- /dev/null
+++ b/xos/core/xoslib/methods/ceilometerview.py
@@ -0,0 +1,940 @@
+import logging
+import requests
+from six.moves import urllib
+import urllib2
+import pytz
+import datetime
+from rest_framework.decorators import api_view
+from rest_framework.response import Response
+from rest_framework.reverse import reverse
+from rest_framework import serializers
+from rest_framework import generics
+from rest_framework.views import APIView
+from core.models import *
+from ceilometer.models import *
+from django.forms import widgets
+from django.utils import datastructures
+from django.utils.translation import ugettext_lazy as _
+from django.utils import timezone
+from syndicate_storage.models import Volume
+from django.core.exceptions import PermissionDenied
+
+# This REST API endpoint provides information that the ceilometer view needs to display
+LOG = logging.getLogger(__name__)
+
+def getTenantCeilometerProxyURL(user):
+    monitoring_channel = None
+    for obj in MonitoringChannel.get_tenant_objects().all():
+        if (obj.creator.username == user.username):
+            monitoring_channel = obj
+            break
+    if not monitoring_channel:
+        raise XOSMissingField("Monitoring channel is missing for this tenant...Create one and invoke this REST API")
+    #TODO: Wait until URL is completely UP
+    while True:
+        try:
+            response = urllib2.urlopen(monitoring_channel.ceilometer_url,timeout=1)
+            break
+        except urllib2.HTTPError, e:
+            LOG.info('SRIKANTH: HTTP error %(reason)s' % {'reason':e.reason})
+            break
+        except urllib2.URLError, e:
+            LOG.info('SRIKANTH: URL error %(reason)s' % {'reason':e.reason})
+            pass
+    return monitoring_channel.ceilometer_url
+
+def getTenantControllerTenantMap(user):
+    tenantmap={}
+    for slice in Slice.objects.filter(creator=user):
+        for cs in slice.controllerslices.all():
+            if cs.tenant_id:
+                tenantmap[cs.tenant_id] = cs.slice.name
+    return tenantmap
+
+def build_url(path, q, params=None):
+    """Convert list of dicts and a list of params to query url format.
+
+    This will convert the following:
+        "[{field=this,op=le,value=34},
+          {field=that,op=eq,value=foo,type=string}],
+         ['foo=bar','sna=fu']"
+    to:
+        "?q.field=this&q.field=that&
+          q.op=le&q.op=eq&
+          q.type=&q.type=string&
+          q.value=34&q.value=foo&
+          foo=bar&sna=fu"
+    """
+    if q:
+        query_params = {'q.field': [],
+                        'q.value': [],
+                        'q.op': [],
+                        'q.type': []}
+
+        for query in q:
+            for name in ['field', 'op', 'value', 'type']:
+                query_params['q.%s' % name].append(query.get(name, ''))
+
+        # Transform the dict to a sequence of two-element tuples in fixed
+        # order, then the encoded string will be consistent in Python 2&3.
+        new_qparams = sorted(query_params.items(), key=lambda x: x[0])
+        path += "?" + urllib.parse.urlencode(new_qparams, doseq=True)
+
+        if params:
+            for p in params:
+                path += '&%s' % p
+    elif params:
+        path += '?%s' % params[0]
+        for p in params[1:]:
+            path += '&%s' % p
+    return path
+
+def concat_url(endpoint, url):
+    """Concatenate endpoint and final URL.
+
+    E.g., "http://keystone/v2.0/" and "/tokens" are concatenated to
+    "http://keystone/v2.0/tokens".
+
+    :param endpoint: the base URL
+    :param url: the final URL
+    """
+    return "%s/%s" % (endpoint.rstrip("/"), url.strip("/"))
+
+def resource_list(request, query=None, ceilometer_url=None, ceilometer_usage_object=None):
+    """List the resources."""
+    url = concat_url(ceilometer_url, build_url('/v2/resources', query))
+    try:
+        response = requests.get(url)
+    except requests.exceptions.RequestException as e:
+        raise e
+    return response.json()
+
+def sample_list(request, meter_name, ceilometer_url=None, query=None, limit=None):
+    """List the samples for this meters."""
+    params = ['limit=%s' % limit] if limit else []
+    url = concat_url(ceilometer_url, build_url('/v2/samples', query, params))
+    try:
+        response = requests.get(url)
+    except requests.exceptions.RequestException as e:
+        raise e
+    return response.json()
+
+def meter_list(request, ceilometer_url=None, query=None):
+    """List the user's meters."""
+    url = concat_url(ceilometer_url, build_url('/v2/meters', query))
+    try:
+        response = requests.get(url)
+    except requests.exceptions.RequestException as e:
+        raise e
+    return response.json()
+
+
+def statistic_list(request, meter_name, ceilometer_url=None, query=None, period=None):
+    """List of statistics."""
+    p = ['period=%s' % period] if period else []
+    url = concat_url(ceilometer_url, build_url('/v2/meters/' + meter_name + '/statistics', query, p))
+    try:
+        response = requests.get(url)
+    except requests.exceptions.RequestException as e:
+        raise e
+    return response.json()
+
+def diff_lists(a, b):
+    if not a:
+        return []
+    elif not b:
+        return a
+    else:
+        return list(set(a) - set(b))
+
+class Meters(object):
+    """Class for listing of available meters.
+
+    It is listing meters defined in this class that are available
+    in Ceilometer meter_list.
+
+    It is storing information that is not available in Ceilometer, i.e.
+    label, description.
+
+    """
+
+    def __init__(self, request=None, ceilometer_meter_list=None, ceilometer_url=None, tenant_map=None):
+        # Storing the request.
+        self._request = request
+        self.ceilometer_url = ceilometer_url
+        self.tenant_map = tenant_map
+
+        # Storing the Ceilometer meter list
+        if ceilometer_meter_list:
+            self._ceilometer_meter_list = ceilometer_meter_list
+        else:
+            try:
+                query=[]
+                self._ceilometer_meter_list = meter_list(request, self.ceilometer_url, query)
+                #LOG.info('SRIKANTH: meters=%(meters)s'%{'meters':[m.project_id for m in self._ceilometer_meter_list]})
+            except requests.exceptions.RequestException as e:
+                self._ceilometer_meter_list = []
+                raise e
+
+        # Storing the meters info categorized by their services.
+        self._nova_meters_info = self._get_nova_meters_info()
+        self._neutron_meters_info = self._get_neutron_meters_info()
+        self._glance_meters_info = self._get_glance_meters_info()
+        self._cinder_meters_info = self._get_cinder_meters_info()
+        self._swift_meters_info = self._get_swift_meters_info()
+        self._kwapi_meters_info = self._get_kwapi_meters_info()
+        self._ipmi_meters_info = self._get_ipmi_meters_info()
+        self._vcpe_meters_info = self._get_vcpe_meters_info()
+        self._sdn_meters_info = self._get_sdn_meters_info()
+
+        # Storing the meters info of all services together.
+        all_services_meters = (self._nova_meters_info,
+                               self._neutron_meters_info,
+                               self._glance_meters_info,
+                               self._cinder_meters_info,
+                               self._swift_meters_info,
+                               self._kwapi_meters_info,
+                               self._ipmi_meters_info,
+                               self._vcpe_meters_info,
+                               self._sdn_meters_info)
+        self._all_meters_info = {}
+        for service_meters in all_services_meters:
+            self._all_meters_info.update(dict([(meter_name, meter_info)
+                                               for meter_name, meter_info
+                                               in service_meters.items()]))
+
+        # Here will be the cached Meter objects, that will be reused for
+        # repeated listing.
+        self._cached_meters = {}
+
+    def list_all(self, only_meters=None, except_meters=None):
+        """Returns a list of meters based on the meters names.
+
+        :Parameters:
+          - `only_meters`: The list of meter names we want to show.
+          - `except_meters`: The list of meter names we don't want to show.
+        """
+
+        return self._list(only_meters=only_meters,
+                          except_meters=except_meters)
+
+    def list_nova(self, except_meters=None):
+        """Returns a list of meters tied to nova.
+
+        :Parameters:
+          - `except_meters`: The list of meter names we don't want to show.
+        """
+
+        return self._list(only_meters=self._nova_meters_info.keys(),
+                          except_meters=except_meters)
+
+    def list_neutron(self, except_meters=None):
+        """Returns a list of meters tied to neutron.
+
+        :Parameters:
+          - `except_meters`: The list of meter names we don't want to show.
+        """
+
+        return self._list(only_meters=self._neutron_meters_info.keys(),
+                          except_meters=except_meters)
+
+    def list_glance(self, except_meters=None):
+        """Returns a list of meters tied to glance.
+
+        :Parameters:
+          - `except_meters`: The list of meter names we don't want to show.
+        """
+
+        return self._list(only_meters=self._glance_meters_info.keys(),
+                          except_meters=except_meters)
+
+    def list_cinder(self, except_meters=None):
+        """Returns a list of meters tied to cinder.
+
+        :Parameters:
+          - `except_meters`: The list of meter names we don't want to show.
+        """
+
+        return self._list(only_meters=self._cinder_meters_info.keys(),
+                          except_meters=except_meters)
+
+    def list_swift(self, except_meters=None):
+        """Returns a list of meters tied to swift.
+
+        :Parameters:
+          - `except_meters`: The list of meter names we don't want to show.
+        """
+
+        return self._list(only_meters=self._swift_meters_info.keys(),
+                          except_meters=except_meters)
+
+    def list_kwapi(self, except_meters=None):
+        """Returns a list of meters tied to kwapi.
+
+        :Parameters:
+          - `except_meters`: The list of meter names we don't want to show.
+        """
+
+        return self._list(only_meters=self._kwapi_meters_info.keys(),
+                          except_meters=except_meters)
+
+    def list_ipmi(self, except_meters=None):
+        """Returns a list of meters tied to ipmi
+
+        :Parameters:
+          - `except_meters`: The list of meter names we don't want to show
+        """
+
+        return self._list(only_meters=self._ipmi_meters_info.keys(),
+                          except_meters=except_meters)
+
+    def list_vcpe(self, except_meters=None):
+        """Returns a list of meters tied to vcpe service
+
+        :Parameters:
+          - `except_meters`: The list of meter names we don't want to show
+        """
+
+        return self._list(only_meters=self._vcpe_meters_info.keys(),
+                          except_meters=except_meters)
+
+    def list_sdn(self, except_meters=None):
+        """Returns a list of meters tied to sdn service
+
+        :Parameters:
+          - `except_meters`: The list of meter names we don't want to show
+        """
+
+        return self._list(only_meters=self._sdn_meters_info.keys(),
+                          except_meters=except_meters)
+
+    def list_other_services(self, except_meters=None):
+        """Returns a list of meters tied to ipmi
+
+        :Parameters:
+          - `except_meters`: The list of meter names we don't want to show
+        """
+        other_service_meters = [m for m in self._ceilometer_meter_list
+                                if m.name not in self._all_meters_info.keys()]
+        other_service_meters = diff_lists(other_service_meters, except_meters)
+
+        meters = []
+        for meter in other_service_meters:
+            self._cached_meters[meter.name] = meter
+            meters.append(meter)
+        return meters
+
+    def _list(self, only_meters=None, except_meters=None):
+        """Returns a list of meters based on the meters names.
+
+        :Parameters:
+          - `only_meters`: The list of meter names we want to show.
+          - `except_meters`: The list of meter names we don't want to show.
+        """
+
+        # Get all wanted meter names.
+        if only_meters:
+            meter_names = only_meters
+        else:
+            meter_names = [meter_name for meter_name
+                           in self._all_meters_info.keys()]
+
+        meter_names = diff_lists(meter_names, except_meters)
+        # Collect meters for wanted meter names.
+        return self._get_meters(meter_names)
+
+    def _get_meters(self, meter_names):
+        """Obtain meters based on meter_names.
+
+        The meters that do not exist in Ceilometer meter list are left out.
+
+        :Parameters:
+          - `meter_names`: A list of meter names we want to fetch.
+        """
+
+        meters = []
+        for meter_name in meter_names:
+            meter = self._get_meter(meter_name)
+            if meter:
+                meters.append(meter)
+        return meters
+
+    def _get_meter(self, meter_name):
+        """Obtains a meter.
+
+        Obtains meter either from cache or from Ceilometer meter list
+        joined with statically defined meter info like label and description.
+
+        :Parameters:
+          - `meter_name`: A meter name we want to fetch.
+        """
+        meter = self._cached_meters.get(meter_name, None)
+        if not meter:
+            meter_candidates = [m for m in self._ceilometer_meter_list
+                                if m["name"] == meter_name]
+
+            if meter_candidates:
+                meter_info = self._all_meters_info.get(meter_name, None)
+                if meter_info:
+                    label = meter_info["label"]
+                    description = meter_info["description"]
+                else:
+                    label = ""
+                    description = ""
+                meter = meter_candidates[0]
+                meter["label"] = label
+                meter["description"] = description
+                if meter["project_id"] in self.tenant_map.keys():
+                    meter["project_name"] = self.tenant_map[meter["project_id"]]
+                else:
+                    meter["project_name"] = meter["project_id"]
+
+                self._cached_meters[meter_name] = meter
+
+        return meter
+
+    def _get_nova_meters_info(self):
+        """Returns additional info for each meter.
+
+        That will be used for augmenting the Ceilometer meter.
+        """
+
+        # TODO(lsmola) Unless the Ceilometer will provide the information
+        # below, I need to define it as a static here. I will be joining this
+        # to info that I am able to obtain from Ceilometer meters, hopefully
+        # some day it will be supported all.
+        meters_info = datastructures.SortedDict([
+            ("instance", {
+                'label': '',
+                'description': _("Existence of instance"),
+            }),
+            ("instance:<type>", {
+                'label': '',
+                'description': _("Existence of instance <type> "
+                                 "(openstack types)"),
+            }),
+            ("memory", {
+                'label': '',
+                'description': _("Volume of RAM"),
+            }),
+            ("memory.usage", {
+                'label': '',
+                'description': _("Volume of RAM used"),
+            }),
+            ("cpu", {
+                'label': '',
+                'description': _("CPU time used"),
+            }),
+            ("cpu_util", {
+                'label': '',
+                'description': _("Average CPU utilization"),
+            }),
+            ("vcpus", {
+                'label': '',
+                'description': _("Number of VCPUs"),
+            }),
+            ("network.incoming.bytes.rate", {
+                'label': '',
+                'description': _("Average rate per sec of incoming "
+                                 "bytes on a VM network interface"),
+            }),
+            ("network.outgoing.bytes.rate", {
+                'label': '',
+                'description': _("Average rate per sec of outgoing "
+                                 "bytes on a VM network interface"),
+            }),
+        ])
+        # Adding flavor based meters into meters_info dict
+        # TODO(lsmola) this kind of meter will be probably deprecated
+        # https://bugs.launchpad.net/ceilometer/+bug/1208365 . Delete it then.
+        #for flavor in get_flavor_names(self._request):
+        #    name = 'instance:%s' % flavor
+        #    meters_info[name] = dict(meters_info["instance:<type>"])
+
+        #    meters_info[name]['description'] = (
+        #        _('Duration of instance type %s (openstack flavor)') %
+        #        flavor)
+
+        # TODO(lsmola) allow to set specific in local_settings. For all meters
+        # because users can have their own agents and meters.
+        return meters_info
+
+    def _get_neutron_meters_info(self):
+        """Returns additional info for each meter.
+
+        That will be used for augmenting the Ceilometer meter.
+        """
+
+        # TODO(lsmola) Unless the Ceilometer will provide the information
+        # below, I need to define it as a static here. I will be joining this
+        # to info that I am able to obtain from Ceilometer meters, hopefully
+        # some day it will be supported all.
+        return datastructures.SortedDict([
+            ('network', {
+                'label': '',
+                'description': _("Existence of network"),
+            }),
+            ('subnet', {
+                'label': '',
+                'description': _("Existence of subnet"),
+            }),
+            ('port', {
+                'label': '',
+                'description': _("Existence of port"),
+            }),
+            ('ip.floating', {
+                'label': '',
+                'description': _("Existence of floating ip"),
+            }),
+        ])
+
+    def _get_glance_meters_info(self):
+        """Returns additional info for each meter.
+
+        That will be used for augmenting the Ceilometer meter.
+        """
+
+        # TODO(lsmola) Unless the Ceilometer will provide the information
+        # below, I need to define it as a static here. I will be joining this
+        # to info that I am able to obtain from Ceilometer meters, hopefully
+        # some day it will be supported all.
+        return datastructures.SortedDict([
+            ('image', {
+                'label': '',
+                'description': _("Image existence check"),
+            }),
+            ('image.size', {
+                'label': '',
+                'description': _("Uploaded image size"),
+            }),
+            ('image.update', {
+                'label': '',
+                'description': _("Number of image updates"),
+            }),
+            ('image.upload', {
+                'label': '',
+                'description': _("Number of image uploads"),
+            }),
+            ('image.delete', {
+                'label': '',
+                'description': _("Number of image deletions"),
+            }),
+            ('image.download', {
+                'label': '',
+                'description': _("Image is downloaded"),
+            }),
+            ('image.serve', {
+                'label': '',
+                'description': _("Image is served out"),
+            }),
+        ])
+
+    def _get_cinder_meters_info(self):
+        """Returns additional info for each meter.
+
+        That will be used for augmenting the Ceilometer meter.
+        """
+
+        # TODO(lsmola) Unless the Ceilometer will provide the information
+        # below, I need to define it as a static here. I will be joining this
+        # to info that I am able to obtain from Ceilometer meters, hopefully
+        # some day it will be supported all.
+        return datastructures.SortedDict([
+            ('volume', {
+                'label': '',
+                'description': _("Existence of volume"),
+            }),
+            ('volume.size', {
+                'label': '',
+                'description': _("Size of volume"),
+            }),
+        ])
+
+    def _get_swift_meters_info(self):
+        """Returns additional info for each meter.
+
+        That will be used for augmenting the Ceilometer meter.
+        """
+
+        # TODO(lsmola) Unless the Ceilometer will provide the information
+        # below, I need to define it as a static here. I will be joining this
+        # to info that I am able to obtain from Ceilometer meters, hopefully
+        # some day it will be supported all.
+        return datastructures.SortedDict([
+            ('storage.objects', {
+                'label': '',
+                'description': _("Number of objects"),
+            }),
+            ('storage.objects.size', {
+                'label': '',
+                'description': _("Total size of stored objects"),
+            }),
+            ('storage.objects.containers', {
+                'label': '',
+                'description': _("Number of containers"),
+            }),
+            ('storage.objects.incoming.bytes', {
+                'label': '',
+                'description': _("Number of incoming bytes"),
+            }),
+            ('storage.objects.outgoing.bytes', {
+                'label': '',
+                'description': _("Number of outgoing bytes"),
+            }),
+            ('storage.api.request', {
+                'label': '',
+                'description': _("Number of API requests against swift"),
+            }),
+        ])
+
+    def _get_kwapi_meters_info(self):
+        """Returns additional info for each meter.
+
+        That will be used for augmenting the Ceilometer meter.
+        """
+
+        # TODO(lsmola) Unless the Ceilometer will provide the information
+        # below, I need to define it as a static here. I will be joining this
+        # to info that I am able to obtain from Ceilometer meters, hopefully
+        # some day it will be supported all.
+        return datastructures.SortedDict([
+            ('energy', {
+                'label': '',
+                'description': _("Amount of energy"),
+            }),
+            ('power', {
+                'label': '',
+                'description': _("Power consumption"),
+            }),
+        ])
+
+    def _get_ipmi_meters_info(self):
+        """Returns additional info for each meter
+
+        That will be used for augmenting the Ceilometer meter
+        """
+
+        # TODO(lsmola) Unless the Ceilometer will provide the information
+        # below, I need to define it as a static here. I will be joining this
+        # to info that I am able to obtain from Ceilometer meters, hopefully
+        # some day it will be supported all.
+        return datastructures.SortedDict([
+            ('hardware.ipmi.node.power', {
+                'label': '',
+                'description': _("System Current Power"),
+            }),
+            ('hardware.ipmi.fan', {
+                'label': '',
+                'description': _("Fan RPM"),
+            }),
+            ('hardware.ipmi.temperature', {
+                'label': '',
+                'description': _("Sensor Temperature Reading"),
+            }),
+            ('hardware.ipmi.current', {
+                'label': '',
+                'description': _("Sensor Current Reading"),
+            }),
+            ('hardware.ipmi.voltage', {
+                'label': '',
+                'description': _("Sensor Voltage Reading"),
+            }),
+            ('hardware.ipmi.node.inlet_temperature', {
+                'label': '',
+                'description': _("System Inlet Temperature Reading"),
+            }),
+            ('hardware.ipmi.node.outlet_temperature', {
+                'label': '',
+                'description': _("System Outlet Temperature Reading"),
+            }),
+            ('hardware.ipmi.node.airflow', {
+                'label': '',
+                'description': _("System Airflow Reading"),
+            }),
+            ('hardware.ipmi.node.cups', {
+                'label': '',
+                'description': _("System CUPS Reading"),
+            }),
+            ('hardware.ipmi.node.cpu_util', {
+                'label': '',
+                'description': _("System CPU Utility Reading"),
+            }),
+            ('hardware.ipmi.node.mem_util', {
+                'label': '',
+                'description': _("System Memory Utility Reading"),
+            }),
+            ('hardware.ipmi.node.io_util', {
+                'label': '',
+                'description': _("System IO Utility Reading"),
+            }),
+        ])
+
+    def _get_vcpe_meters_info(self):
+        """Returns additional info for each meter
+
+        That will be used for augmenting the Ceilometer meter
+        """
+
+        # TODO(lsmola) Unless the Ceilometer will provide the information
+        # below, I need to define it as a static here. I will be joining this
+        # to info that I am able to obtain from Ceilometer meters, hopefully
+        # some day it will be supported all.
+        return datastructures.SortedDict([
+            ('vcpe', {
+                'label': '',
+                'description': _("Existence of vcpe instance"),
+            }),
+            ('vcpe.dns.cache.size', {
+                'label': '',
+                'description': _("Number of entries in DNS cache"),
+            }),
+            ('vcpe.dns.total_instered_entries', {
+                'label': '',
+                'description': _("Total number of inserted entries into the cache"),
+            }),
+            ('vcpe.dns.replaced_unexpired_entries', {
+                'label': '',
+                'description': _("Unexpired entries that were thrown out of cache"),
+            }),
+            ('vcpe.dns.queries_answered_locally', {
+                'label': '',
+                'description': _("Number of cache hits"),
+            }),
+            ('vcpe.dns.queries_forwarded', {
+                'label': '',
+                'description': _("Number of cache misses"),
+            }),
+            ('vcpe.dns.server.queries_sent', {
+                'label': '',
+                'description': _("For each upstream server, the number of queries sent"),
+            }),
+            ('vcpe.dns.server.queries_failed', {
+                'label': '',
+                'description': _("For each upstream server, the number of queries failed"),
+            }),
+        ])
+
+    def _get_sdn_meters_info(self):
+        """Returns additional info for each meter
+
+        That will be used for augmenting the Ceilometer meter
+        """
+
+        # TODO(lsmola) Unless the Ceilometer will provide the information
+        # below, I need to define it as a static here. I will be joining this
+        # to info that I am able to obtain from Ceilometer meters, hopefully
+        # some day it will be supported all.
+        return datastructures.SortedDict([
+            ('switch', {
+                'label': '',
+                'description': _("Existence of switch"),
+            }),
+            ('switch.port', {
+                'label': '',
+                'description': _("Existence of port"),
+            }),
+            ('switch.port.receive.packets', {
+                'label': '',
+                'description': _("Packets received on port"),
+            }),
+            ('switch.port.transmit.packets', {
+                'label': '',
+                'description': _("Packets transmitted on port"),
+            }),
+            ('switch.port.receive.drops', {
+                'label': '',
+                'description': _("Drops received on port"),
+            }),
+            ('switch.port.transmit.drops', {
+                'label': '',
+                'description': _("Drops transmitted on port"),
+            }),
+            ('switch.port.receive.errors', {
+                'label': '',
+                'description': _("Errors received on port"),
+            }),
+            ('switch.port.transmit.errors', {
+                'label': '',
+                'description': _("Errors transmitted on port"),
+            }),
+            ('switch.flow', {
+                'label': '',
+                'description': _("Duration of flow"),
+            }),
+            ('switch.flow.packets', {
+                'label': '',
+                'description': _("Packets received"),
+            }),
+            ('switch.table', {
+                'label': '',
+                'description': _("Existence of table"),
+            }),
+            ('switch.table.active.entries', {
+                'label': '',
+                'description': _("Active entries in table"),
+            }),
+        ])
+
+def make_query(user_id=None, tenant_id=None, resource_id=None,
+               user_ids=None, tenant_ids=None, resource_ids=None):
+    """Returns query built from given parameters.
+
+    This query can be then used for querying resources, meters and
+    statistics.
+
+    :Parameters:
+      - `user_id`: user_id, has a priority over list of ids
+      - `tenant_id`: tenant_id, has a priority over list of ids
+      - `resource_id`: resource_id, has a priority over list of ids
+      - `user_ids`: list of user_ids
+      - `tenant_ids`: list of tenant_ids
+      - `resource_ids`: list of resource_ids
+    """
+    user_ids = user_ids or []
+    tenant_ids = tenant_ids or []
+    resource_ids = resource_ids or []
+
+    query = []
+    if user_id:
+        user_ids = [user_id]
+    for u_id in user_ids:
+        query.append({"field": "user_id", "op": "eq", "value": u_id})
+
+    if tenant_id:
+        tenant_ids = [tenant_id]
+    for t_id in tenant_ids:
+        query.append({"field": "project_id", "op": "eq", "value": t_id})
+
+    if resource_id:
+        resource_ids = [resource_id]
+    for r_id in resource_ids:
+        query.append({"field": "resource_id", "op": "eq", "value": r_id})
+
+    return query
+
+def calc_date_args(date_from, date_to, date_options):
+    # TODO(lsmola) all timestamps should probably work with
+    # current timezone. And also show the current timezone in chart.
+    if date_options == "other":
+        try:
+            if date_from:
+                date_from = pytz.utc.localize(
+                    datetime.datetime.strptime(str(date_from), "%Y-%m-%d"))
+            else:
+                # TODO(lsmola) there should be probably the date
+                # of the first sample as default, so it correctly
+                # counts the time window. Though I need ordering
+                # and limit of samples to obtain that.
+                pass
+            if date_to:
+                date_to = pytz.utc.localize(
+                    datetime.datetime.strptime(str(date_to), "%Y-%m-%d"))
+                # It returns the beginning of the day, I want the end of
+                # the day, so I add one day without a second.
+                date_to = (date_to + datetime.timedelta(days=1) -
+                           datetime.timedelta(seconds=1))
+            else:
+                date_to = timezone.now()
+        except Exception:
+            raise ValueError(_("The dates haven't been recognized"))
+    else:
+        try:
+            date_to = timezone.now()
+            date_from = date_to - datetime.timedelta(days=float(date_options))
+        except Exception as e:
+            raise e
+            #raise ValueError(_("The time delta must be a number representing "
+            #                   "the time span in days"))
+    return date_from, date_to
+
+class MetersList(APIView):
+    method_kind = "list"
+    method_name = "meters"
+
+    def get(self, request, format=None):
+        if (not request.user.is_authenticated()):
+            raise PermissionDenied("You must be authenticated in order to use this API")
+        tenant_ceilometer_url = getTenantCeilometerProxyURL(request.user)
+        if (not tenant_ceilometer_url):
+            raise XOSMissingField("Tenant ceilometer URL is missing")
+        tenant_map = getTenantControllerTenantMap(request.user)
+        meters = Meters(request, ceilometer_url=tenant_ceilometer_url, tenant_map=tenant_map)
+        services = {
+            _('Nova'): meters.list_nova(),
+            _('Neutron'): meters.list_neutron(),
+            _('VCPE'): meters.list_vcpe(),
+            _('SDN'): meters.list_sdn(),
+        }
+        return Response(meters._cached_meters.values())
+
+class MeterStatisticsList(APIView):
+    method_kind = "list"
+    method_name = "meterstatistics"
+
+    def get(self, request, format=None):
+        if (not request.user.is_authenticated()):
+            raise PermissionDenied("You must be authenticated in order to use this API")
+        tenant_ceilometer_url = getTenantCeilometerProxyURL(request.user)
+        if (not tenant_ceilometer_url):
+            raise XOSMissingField("Tenant ceilometer URL is missing")
+        tenant_map = getTenantControllerTenantMap(request.user)
+        
+        date_options = request.QUERY_PARAMS.get('period', 1)
+        date_from = request.QUERY_PARAMS.get('date_from', '')
+        date_to = request.QUERY_PARAMS.get('date_to', '')
+
+        try:
+            date_from, date_to = calc_date_args(date_from,
+                                                date_to,
+                                                date_options)
+        except Exception as e:
+           raise e 
+
+        meters = Meters(request, ceilometer_url=tenant_ceilometer_url, tenant_map=tenant_map)
+        services = {
+            _('Nova'): meters.list_nova(),
+            _('Neutron'): meters.list_neutron(),
+            _('VCPE'): meters.list_vcpe(),
+            _('SDN'): meters.list_sdn(),
+        }
+        report_rows = []
+        for service,meters in services.items():
+            for meter in meters:
+                query = make_query(tenant_id=meter["project_id"])
+                statistics = statistic_list(request, meter["name"],
+                                        ceilometer_url=tenant_ceilometer_url, query=query, period=3600*24)
+                statistic = statistics[0]
+                row = {"name": 'none',
+                       "project": meter["project_name"],
+                       "meter": meter["name"],
+                       "description": meter["description"],
+                       "service": service,
+                       "time": statistic["period_end"],
+                       "value": statistic["avg"],
+                       "unit": meter["unit"]}
+                report_rows.append(row)
+
+        return Response(report_rows)
+
+
+class MeterSamplesList(APIView):
+    method_kind = "list"
+    method_name = "metersamples"
+
+    def get(self, request, format=None):
+        if (not request.user.is_authenticated()):
+            raise PermissionDenied("You must be authenticated in order to use this API")
+        tenant_ceilometer_url = getTenantCeilometerProxyURL(request.user)
+        if (not tenant_ceilometer_url):
+            raise XOSMissingField("Tenant ceilometer URL is missing")
+        meter_name = request.QUERY_PARAMS.get('meter', None)
+        tenant_id = request.QUERY_PARAMS.get('tenant', None)
+        if not meter_name:
+            raise XOSMissingField("Meter name in query params is missing")
+        query = []
+        if tenant_id:
+            query.extend(make_query(tenant_id="default_admin_tenant"))
+        query.append({"field": "meter", "op": "eq", "value": meter_name})
+        samples = sample_list(request, meter_name,
+                           ceilometer_url=tenant_ceilometer_url, query=query, limit=10) 
+        return Response(samples)
diff --git a/xos/observers/monitoring_channel/templates/ceilometer_proxy_server.py b/xos/observers/monitoring_channel/templates/ceilometer_proxy_server.py
index c6be286..249c965 100644
--- a/xos/observers/monitoring_channel/templates/ceilometer_proxy_server.py
+++ b/xos/observers/monitoring_channel/templates/ceilometer_proxy_server.py
@@ -121,7 +121,7 @@
     i=0
     user_specified_tenants=[]
     for field in query_params['q.field']:
-        if field != 'project_id':
+        if (field != 'project_id') and (field != 'project'):
             query = {}
             query['field']=field
             if query_params['q.op'][i] != '':
@@ -195,11 +195,13 @@
              "q.op": [],
              "q.type": [],
              "q.value": [],
+             "limit": None,
         }
         query_params = web.input(**keyword_args)
         new_query, user_specified_tenants = filter_query_params(query_params)
 
         client = ceilometerclient()
+        limit=query_params.limit
         samples=[]
         for (k,v) in config.items('allowed_tenants'):
               if user_specified_tenants and (k not in user_specified_tenants):
@@ -209,7 +211,7 @@
               query = make_query(tenant_id=k)
               final_query.extend(query)
               logger.debug('final query=%s',final_query)
-              results = client.samples.list(q=final_query)
+              results = client.new_samples.list(q=final_query,limit=limit)
               samples.extend(results)
         return json.dumps([ob._info for ob in samples])