summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ceilometer/api/controllers/v2.py3
-rw-r--r--ceilometer/collector/service.py10
-rw-r--r--ceilometer/compute/instance.py11
-rw-r--r--ceilometer/nova_client.py48
-rw-r--r--ceilometer/pipeline.py2
-rw-r--r--ceilometer/service.py6
-rw-r--r--ceilometer/storage/impl_mongodb.py2
-rw-r--r--doc/source/configuration.rst1
-rw-r--r--doc/source/measurements.rst9
-rw-r--r--etc/ceilometer/ceilometer.conf.sample5
-rw-r--r--tests/compute/test_instance.py58
-rw-r--r--tests/compute/test_pollsters.py3
-rw-r--r--tests/test_novaclient.py127
13 files changed, 225 insertions, 60 deletions
diff --git a/ceilometer/api/controllers/v2.py b/ceilometer/api/controllers/v2.py
index c58241ee..8f98feb3 100644
--- a/ceilometer/api/controllers/v2.py
+++ b/ceilometer/api/controllers/v2.py
@@ -139,8 +139,7 @@ def _query_to_kwargs(query, db_func):
if trans:
for k in trans:
if k not in valid_keys:
- raise wsme.exc.UnknownArgument(i.field,
- "unrecognized query field")
+ raise wsme.exc.UnknownArgument(k, "unrecognized query field")
kwargs[k] = trans[k]
return kwargs
diff --git a/ceilometer/collector/service.py b/ceilometer/collector/service.py
index 2f4ddf14..eda82706 100644
--- a/ceilometer/collector/service.py
+++ b/ceilometer/collector/service.py
@@ -131,11 +131,11 @@ class CollectorService(service.PeriodicService):
data = [data]
for meter in data:
- LOG.info('metering data %s for %s @ %s: %s',
- meter['counter_name'],
- meter['resource_id'],
- meter.get('timestamp', 'NO TIMESTAMP'),
- meter['counter_volume'])
+ LOG.debug('metering data %s for %s @ %s: %s',
+ meter['counter_name'],
+ meter['resource_id'],
+ meter.get('timestamp', 'NO TIMESTAMP'),
+ meter['counter_volume'])
if meter_api.verify_signature(meter, cfg.CONF.metering_secret):
try:
# Convert the timestamp to a datetime instance.
diff --git a/ceilometer/compute/instance.py b/ceilometer/compute/instance.py
index dff5ec6e..82026c6a 100644
--- a/ceilometer/compute/instance.py
+++ b/ceilometer/compute/instance.py
@@ -24,25 +24,26 @@ INSTANCE_PROPERTIES = [
# Type properties
'architecture',
# Location properties
- 'availability_zone',
'kernel_id',
'os_type',
'ramdisk_id',
# Capacity properties
- 'disk_gb',
'ephemeral_gb',
- 'memory_mb',
- 'root_gb',
- 'vcpus']
+ 'root_gb']
def get_metadata_from_object(instance):
"""Return a metadata dictionary for the instance.
"""
metadata = {
+ 'availability_zone': getattr(instance,
+ 'OS-EXT-AZ:availability_zone', u''),
'display_name': instance.name,
'name': getattr(instance, 'OS-EXT-SRV-ATTR:instance_name', u''),
'instance_type': (instance.flavor['id'] if instance.flavor else None),
+ 'disk_gb': (instance.flavor['disk'] if instance.flavor else None),
+ 'memory_mb': (instance.flavor['ram'] if instance.flavor else None),
+ 'vcpus': (instance.flavor['vcpus'] if instance.flavor else None),
'host': instance.hostId,
# Image properties
'image_ref': (instance.image['id'] if instance.image else None),
diff --git a/ceilometer/nova_client.py b/ceilometer/nova_client.py
index 9bbff9ff..e8f4714d 100644
--- a/ceilometer/nova_client.py
+++ b/ceilometer/nova_client.py
@@ -16,6 +16,7 @@
import functools
+import novaclient
from novaclient.v1_1 import client as nova_client
from oslo.config import cfg
@@ -44,27 +45,58 @@ class Client(object):
"""Returns a nova Client object."""
conf = cfg.CONF
tenant = conf.os_tenant_id and conf.os_tenant_id or conf.os_tenant_name
+ endpoint_type = cfg.CONF.os_endpoint_type
self.nova_client = nova_client.Client(username=cfg.CONF.os_username,
api_key=cfg.CONF.os_password,
project_id=tenant,
auth_url=cfg.CONF.os_auth_url,
+ endpoint_type=endpoint_type,
no_cache=True)
- def _with_flavor(self, instances):
- flavors = dict((f.id, f) for f in self.nova_client.flavors.list())
+ def _with_flavor_and_image(self, instances):
for instance in instances:
- fid = instance.flavor['id']
- try:
- instance.flavor['name'] = flavors[fid].name
- except KeyError:
- instance.flavor['name'] = 'unknown-id-%s' % fid
+ self._with_flavor(instance)
+ self._with_image(instance)
+
return instances
+ def _with_flavor(self, instance):
+ fid = instance.flavor['id']
+ try:
+ flavor = self.nova_client.flavors.get(fid)
+ except novaclient.exceptions.NotFound:
+ flavor = None
+
+ attr_defaults = [('name', 'unknown-id-%s' % fid),
+ ('vcpus', 0), ('ram', 0), ('disk', 0)]
+ for attr, default in attr_defaults:
+ if not flavor:
+ instance.flavor[attr] = default
+ continue
+ instance.flavor[attr] = getattr(flavor, attr, default)
+
+ def _with_image(self, instance):
+ iid = instance.image['id']
+ try:
+ image = self.nova_client.images.get(iid)
+ except novaclient.exceptions.NotFound:
+ instance.image['name'] = 'unknown-id-%s' % iid
+ instance.kernel_id = None
+ instance.ramdisk_id = None
+ return
+
+ instance.image['name'] = getattr(image, 'name')
+ image_metadata = getattr(image, 'metadata', None)
+
+ for attr in ['kernel_id', 'ramdisk_id']:
+ ameta = image_metadata.get(attr, None) if image_metadata else None
+ setattr(instance, attr, ameta)
+
@logged
def instance_get_all_by_host(self, hostname):
"""Returns list of instances on particular host."""
search_opts = {'host': hostname, 'all_tenants': True}
- return self._with_flavor(self.nova_client.servers.list(
+ return self._with_flavor_and_image(self.nova_client.servers.list(
detailed=True,
search_opts=search_opts))
diff --git a/ceilometer/pipeline.py b/ceilometer/pipeline.py
index 8609a64c..65d4dc1a 100644
--- a/ceilometer/pipeline.py
+++ b/ceilometer/pipeline.py
@@ -230,7 +230,7 @@ class Pipeline(object):
transformed_counters = []
for counter in counters:
- LOG.audit("Pipeline %s: Transform counter %s from %s transformer",
+ LOG.debug("Pipeline %s: Transform counter %s from %s transformer",
self, counter, start)
counter = self._transform_counter(start, ctxt, counter, source)
if counter:
diff --git a/ceilometer/service.py b/ceilometer/service.py
index 9286abd1..5cabe8f0 100644
--- a/ceilometer/service.py
+++ b/ceilometer/service.py
@@ -33,7 +33,7 @@ cfg.CONF.register_opts([
default=600,
help='seconds between running periodic tasks'),
cfg.StrOpt('host',
- default=socket.getfqdn(),
+ default=socket.gethostname(),
help='Name of this node. This can be an opaque identifier. '
'It is not necessarily a hostname, FQDN, or IP address. '
'However, the node name must be valid within '
@@ -58,6 +58,10 @@ CLI_OPTIONS = [
default=os.environ.get('OS_AUTH_URL',
'http://localhost:5000/v2.0'),
help='Auth URL to use for openstack service access'),
+ cfg.StrOpt('os-endpoint-type',
+ default=os.environ.get('OS_ENDPOINT_TYPE', 'publicURL'),
+ help='Type of endpoint in Identity service catalog to use for '
+ 'communication with OpenStack services.'),
]
cfg.CONF.register_cli_opts(CLI_OPTIONS)
diff --git a/ceilometer/storage/impl_mongodb.py b/ceilometer/storage/impl_mongodb.py
index 77ca0b5d..e364b805 100644
--- a/ceilometer/storage/impl_mongodb.py
+++ b/ceilometer/storage/impl_mongodb.py
@@ -264,6 +264,8 @@ class Connection(base.Connection):
('timestamp', pymongo.ASCENDING),
('source', pymongo.ASCENDING),
], name='meter_idx')
+ self.db.meter.ensure_index([('timestamp', pymongo.DESCENDING)],
+ name='timestamp_idx')
def upgrade(self, version=None):
pass
diff --git a/doc/source/configuration.rst b/doc/source/configuration.rst
index 73104f56..9ecb629a 100644
--- a/doc/source/configuration.rst
+++ b/doc/source/configuration.rst
@@ -45,6 +45,7 @@ os_password admin Password
os_tenant_id Tenant ID to use for openstack service access
os_tenant_name admin Tenant name to use for openstack service access
os_auth_url http://localhost:5000/v2.0 Auth URL to use for openstack service access
+os_endpoint_type publicURL Endpoint type in the catalog to use to access services
database_connection mongodb://localhost:27017/ceilometer Database connection string
metering_api_port 8777 The port for the ceilometer API server
disabled_central_pollsters List of central pollsters to skip loading
diff --git a/doc/source/measurements.rst b/doc/source/measurements.rst
index f53a7e08..d16b1aaf 100644
--- a/doc/source/measurements.rst
+++ b/doc/source/measurements.rst
@@ -78,11 +78,10 @@ disk.read.bytes Cumulative B inst ID pollster Volume o
disk.write.bytes Cumulative B inst ID pollster Volume of write in B
disk.root.size Gauge GB inst ID notification Size of root disk in GB
disk.ephemeral.size Gauge GB inst ID notification Size of ephemeral disk in GB
-network.incoming.bytes Cumulative B iface ID pollster number of incoming bytes on the network
-network.outgoing.bytes Cumulative B iface ID pollster number of outgoing bytes on the network
-network.incoming.packets Cumulative packets iface ID pollster number of incoming packets
-network.outgoing.packets Cumulative packets iface ID pollster number of outgoing packets
-
+network.incoming.bytes Cumulative B iface ID pollster number of incoming bytes on the network for a VM interface
+network.outgoing.bytes Cumulative B iface ID pollster number of outgoing bytes on the network for a VM interface
+network.incoming.packets Cumulative packets iface ID pollster number of incoming packets for a VM interface
+network.outgoing.packets Cumulative packets iface ID pollster number of outgoing packets for a VM interface
======================== ========== ======== ======== ============ =======================================================
Network (Quantum)
diff --git a/etc/ceilometer/ceilometer.conf.sample b/etc/ceilometer/ceilometer.conf.sample
index d028fe4d..db274eda 100644
--- a/etc/ceilometer/ceilometer.conf.sample
+++ b/etc/ceilometer/ceilometer.conf.sample
@@ -43,6 +43,9 @@
# Auth URL to use for openstack service access (string value)
#os_auth_url=
+# Type of endpoint in Identity service catalog to use for
+# communication with OpenStack services. (string value)
+#os_endpoint_type=publicURL
######## defined in ceilometer.api ########
@@ -477,4 +480,4 @@
#password=<None>
-# Total option count: 105
+# Total option count: 106
diff --git a/tests/compute/test_instance.py b/tests/compute/test_instance.py
index 09cc0afa..9a199f5c 100644
--- a/tests/compute/test_instance.py
+++ b/tests/compute/test_instance.py
@@ -53,49 +53,53 @@ class TestLocationMetadata(unittest.TestCase):
self.INSTANCE_PROPERTIES = {'name': 'display name',
'OS-EXT-SRV-ATTR:instance_name':
'instance-000001',
+ 'availability_zone': None,
+ 'OS-EXT-AZ:availability_zone':
+ 'foo-zone',
'reservation_id': 'reservation id',
'architecture': 'x86_64',
- 'availability_zone': 'zone1',
'kernel_id': 'kernel id',
'os_type': 'linux',
'ramdisk_id': 'ramdisk id',
- 'disk_gb': 10,
'ephemeral_gb': 7,
- 'memory_mb': 2048,
'root_gb': 3,
- 'vcpus': 1,
'image': {'id': 1,
'links': [{"rel": "bookmark",
'href': 2}]},
- 'flavor': {'id': 1},
- 'hostId': '1234-5678'}
+ 'hostId': '1234-5678',
+ 'flavor': {'id': 1,
+ 'disk': 0,
+ 'ram': 512,
+ 'vcpus': 2},
+ 'metadata': {'metering.autoscale.group':
+ 'X' * 512,
+ 'metering.ephemeral_gb': 42}}
self.instance = FauxInstance(**self.INSTANCE_PROPERTIES)
- self.instance.host = 'made-up-hostname'
- m = mock.MagicMock()
- m.flavorid = 1
- self.instance.instance_type = m
def test_metadata(self):
md = instance.get_metadata_from_object(self.instance)
iprops = self.INSTANCE_PROPERTIES
- for name in md.keys():
- actual = md[name]
- print 'checking', name, actual
- if name == 'name':
- assert actual == iprops['OS-EXT-SRV-ATTR:instance_name']
- elif name == 'host':
- assert actual == iprops['hostId']
- elif name == 'display_name':
- assert actual == iprops['name']
- elif name == 'instance_type':
- assert actual == iprops['flavor']['id']
- elif name == 'image_ref':
- assert actual == iprops['image']['id']
- elif name == 'image_ref_url':
- assert actual == iprops['image']['links'][0]['href']
- else:
- assert actual == iprops[name]
+ self.assertEqual(md['availability_zone'],
+ iprops['OS-EXT-AZ:availability_zone'])
+ self.assertEqual(md['name'], iprops['OS-EXT-SRV-ATTR:instance_name'])
+ self.assertEqual(md['disk_gb'], iprops['flavor']['disk'])
+ self.assertEqual(md['display_name'], iprops['name'])
+ self.assertEqual(md['instance_type'], iprops['flavor']['id'])
+ self.assertEqual(md['image_ref'], iprops['image']['id'])
+ self.assertEqual(md['image_ref_url'],
+ iprops['image']['links'][0]['href'])
+ self.assertEqual(md['memory_mb'], iprops['flavor']['ram'])
+ self.assertEqual(md['vcpus'], iprops['flavor']['vcpus'])
+ self.assertEqual(md['host'], iprops['hostId'])
+
+ self.assertEqual(md['reservation_id'], iprops['reservation_id'])
+ self.assertEqual(md['kernel_id'], iprops['kernel_id'])
+ self.assertEqual(md['ramdisk_id'], iprops['ramdisk_id'])
+ self.assertEqual(md['architecture'], iprops['architecture'])
+ self.assertEqual(md['os_type'], iprops['os_type'])
+ self.assertEqual(md['ephemeral_gb'], iprops['ephemeral_gb'])
+ self.assertEqual(md['root_gb'], iprops['root_gb'])
def test_metadata_empty_image(self):
self.INSTANCE_PROPERTIES['image'] = ''
diff --git a/tests/compute/test_pollsters.py b/tests/compute/test_pollsters.py
index 1aa5543c..526a7dbb 100644
--- a/tests/compute/test_pollsters.py
+++ b/tests/compute/test_pollsters.py
@@ -41,7 +41,8 @@ class TestPollsterBase(test_base.TestCase):
setattr(self.instance, 'OS-EXT-SRV-ATTR:instance_name',
self.instance.name)
self.instance.id = 1
- self.instance.flavor = {'name': 'm1.small', 'id': 2}
+ self.instance.flavor = {'name': 'm1.small', 'id': 2, 'vcpus': 1,
+ 'ram': 512, 'disk': 0}
class TestInstancePollster(TestPollsterBase):
diff --git a/tests/test_novaclient.py b/tests/test_novaclient.py
index ee3715d7..2b563694 100644
--- a/tests/test_novaclient.py
+++ b/tests/test_novaclient.py
@@ -19,6 +19,7 @@
import mock
+import novaclient
from ceilometer.tests import base
from ceilometer import nova_client
@@ -28,6 +29,42 @@ class TestNovaClient(base.TestCase):
def setUp(self):
super(TestNovaClient, self).setUp()
self.nv = nova_client.Client()
+ self.stubs.Set(self.nv.nova_client.flavors, 'get',
+ self.fake_flavors_get)
+ self.stubs.Set(self.nv.nova_client.images, 'get', self.fake_images_get)
+
+ @staticmethod
+ def fake_flavors_get(*args, **kwargs):
+ a = mock.MagicMock()
+ a.id = args[0]
+ if a.id == 1:
+ a.name = 'm1.tiny'
+ elif a.id == 2:
+ a.name = 'm1.large'
+ else:
+ raise novaclient.exceptions.NotFound('foobar')
+ return a
+
+ @staticmethod
+ def fake_images_get(*args, **kwargs):
+ a = mock.MagicMock()
+ a.id = args[0]
+ image_details = {
+ 1: ('ubuntu-12.04-x86', dict(kernel_id=11, ramdisk_id=21)),
+ 2: ('centos-5.4-x64', dict(kernel_id=12, ramdisk_id=22)),
+ 3: ('rhel-6-x64', None),
+ 4: ('rhel-6-x64', dict()),
+ 5: ('rhel-6-x64', dict(kernel_id=11)),
+ 6: ('rhel-6-x64', dict(ramdisk_id=21))
+ }
+
+ if a.id in image_details:
+ a.name = image_details[a.id][0]
+ a.metadata = image_details[a.id][1]
+ else:
+ raise novaclient.exceptions.NotFound('foobar')
+
+ return a
@staticmethod
def fake_flavors_list():
@@ -44,31 +81,113 @@ class TestNovaClient(base.TestCase):
a = mock.MagicMock()
a.id = 42
a.flavor = {'id': 1}
+ a.image = {'id': 1}
return [a]
def test_instance_get_all_by_host(self):
- self.stubs.Set(self.nv.nova_client.flavors, 'list',
- self.fake_flavors_list)
self.stubs.Set(self.nv.nova_client.servers, 'list',
self.fake_servers_list)
instances = self.nv.instance_get_all_by_host('foobar')
self.assertEqual(len(instances), 1)
self.assertEqual(instances[0].flavor['name'], 'm1.tiny')
+ self.assertEqual(instances[0].image['name'], 'ubuntu-12.04-x86')
+ self.assertEqual(instances[0].kernel_id, 11)
+ self.assertEqual(instances[0].ramdisk_id, 21)
@staticmethod
def fake_servers_list_unknown_flavor(*args, **kwargs):
a = mock.MagicMock()
a.id = 42
a.flavor = {'id': 666}
+ a.image = {'id': 1}
return [a]
def test_instance_get_all_by_host_unknown_flavor(self):
- self.stubs.Set(self.nv.nova_client.flavors, 'list',
- self.fake_flavors_list)
self.stubs.Set(self.nv.nova_client.servers, 'list',
self.fake_servers_list_unknown_flavor)
instances = self.nv.instance_get_all_by_host('foobar')
self.assertEqual(len(instances), 1)
self.assertEqual(instances[0].flavor['name'], 'unknown-id-666')
+
+ @staticmethod
+ def fake_servers_list_unknown_image(*args, **kwargs):
+ a = mock.MagicMock()
+ a.id = 42
+ a.flavor = {'id': 1}
+ a.image = {'id': 666}
+ return [a]
+
+ @staticmethod
+ def fake_servers_list_image_missing_metadata(*args, **kwargs):
+ a = mock.MagicMock()
+ a.id = 42
+ a.flavor = {'id': 1}
+ a.image = {'id': args[0]}
+ return [a]
+
+ def test_instance_get_all_by_host_unknown_image(self):
+ self.stubs.Set(self.nv.nova_client.servers, 'list',
+ self.fake_servers_list_unknown_image)
+
+ instances = self.nv.instance_get_all_by_host('foobar')
+ self.assertEqual(len(instances), 1)
+ self.assertEqual(instances[0].image['name'], 'unknown-id-666')
+
+ def test_with_flavor_and_image(self):
+ results = self.nv._with_flavor_and_image(self.fake_servers_list())
+ instance = results[0]
+ self.assertEqual(instance.image['name'], 'ubuntu-12.04-x86')
+ self.assertEqual(instance.flavor['name'], 'm1.tiny')
+ self.assertEqual(instance.kernel_id, 11)
+ self.assertEqual(instance.ramdisk_id, 21)
+
+ def test_with_flavor_and_image_unknown_image(self):
+ instances = self.fake_servers_list_unknown_image()
+ results = self.nv._with_flavor_and_image(instances)
+ instance = results[0]
+ self.assertEqual(instance.image['name'], 'unknown-id-666')
+ self.assertNotEqual(instance.flavor['name'], 'unknown-id-666')
+ self.assertIsNone(instance.kernel_id)
+ self.assertIsNone(instance.ramdisk_id)
+
+ def test_with_flavor_and_image_unknown_flavor(self):
+ instances = self.fake_servers_list_unknown_flavor()
+ results = self.nv._with_flavor_and_image(instances)
+ instance = results[0]
+ self.assertEqual(instance.flavor['name'], 'unknown-id-666')
+ self.assertEqual(instance.flavor['vcpus'], 0)
+ self.assertEqual(instance.flavor['ram'], 0)
+ self.assertEqual(instance.flavor['disk'], 0)
+ self.assertNotEqual(instance.image['name'], 'unknown-id-666')
+ self.assertEqual(instance.kernel_id, 11)
+ self.assertEqual(instance.ramdisk_id, 21)
+
+ def test_with_flavor_and_image_none_metadata(self):
+ instances = self.fake_servers_list_image_missing_metadata(3)
+ results = self.nv._with_flavor_and_image(instances)
+ instance = results[0]
+ self.assertIsNone(instance.kernel_id)
+ self.assertIsNone(instance.ramdisk_id)
+
+ def test_with_flavor_and_image_missing_metadata(self):
+ instances = self.fake_servers_list_image_missing_metadata(4)
+ results = self.nv._with_flavor_and_image(instances)
+ instance = results[0]
+ self.assertIsNone(instance.kernel_id)
+ self.assertIsNone(instance.ramdisk_id)
+
+ def test_with_flavor_and_image_missing_ramdisk(self):
+ instances = self.fake_servers_list_image_missing_metadata(5)
+ results = self.nv._with_flavor_and_image(instances)
+ instance = results[0]
+ self.assertEqual(instance.kernel_id, 11)
+ self.assertIsNone(instance.ramdisk_id)
+
+ def test_with_flavor_and_image_missing_kernel(self):
+ instances = self.fake_servers_list_image_missing_metadata(6)
+ results = self.nv._with_flavor_and_image(instances)
+ instance = results[0]
+ self.assertIsNone(instance.kernel_id)
+ self.assertEqual(instance.ramdisk_id, 21)