diff --git a/ceilometer/compute/instance.py b/ceilometer/compute/instance.py index dff5ec6e0..7b312ef6d 100644 --- a/ceilometer/compute/instance.py +++ b/ceilometer/compute/instance.py @@ -17,6 +17,19 @@ # under the License. """Common code for working with instances """ +from oslo.config import cfg + +OPTS = [ + cfg.ListOpt('reserved_metadata_namespace', + default=['metering.'], + help='list of metadata prefixes resevred for metering use', + ), + cfg.IntOpt('reserved_metadata_length', + default=256, + help='limit on length of reserved metadata values'), +] + +cfg.CONF.register_opts(OPTS) INSTANCE_PROPERTIES = [ # Identity properties @@ -36,6 +49,24 @@ INSTANCE_PROPERTIES = [ 'vcpus'] +def add_reserved_user_metadata(instance, metadata): + limit = cfg.CONF.reserved_metadata_length + user_metadata = {} + for prefix in cfg.CONF.reserved_metadata_namespace: + md = dict( + (k[len(prefix):].replace('.', '_'), + v[:limit] if isinstance(v, basestring) else v) + for k, v in instance.metadata.items() + if (k.startswith(prefix) and + k[len(prefix):].replace('.', '_') not in metadata) + ) + user_metadata.update(md) + if user_metadata: + metadata['user_metadata'] = user_metadata + + return metadata + + def get_metadata_from_object(instance): """Return a metadata dictionary for the instance. """ @@ -57,4 +88,5 @@ def get_metadata_from_object(instance): for name in INSTANCE_PROPERTIES: metadata[name] = getattr(instance, name, u'') - return metadata + + return add_reserved_user_metadata(instance, metadata) diff --git a/tests/compute/test_instance.py b/tests/compute/test_instance.py index e5bb06148..092213840 100644 --- a/tests/compute/test_instance.py +++ b/tests/compute/test_instance.py @@ -67,7 +67,10 @@ class TestLocationMetadata(base.TestCase): 'links': [{"rel": "bookmark", 'href': 2}]}, 'flavor': {'id': 1}, - 'hostId': '1234-5678'} + 'hostId': '1234-5678', + 'metadata': {'metering.autoscale.group': + 'X' * 512, + 'metering.ephemeral_gb': 42}} self.instance = FauxInstance(**self.INSTANCE_PROPERTIES) self.instance.host = 'made-up-hostname' @@ -93,6 +96,10 @@ class TestLocationMetadata(base.TestCase): assert actual == iprops['image']['id'] elif name == 'image_ref_url': assert actual == iprops['image']['links'][0]['href'] + elif name == 'user_metadata': + expected = iprops['metadata']['metering.autoscale.group'][:256] + self.assertEqual(actual['autoscale_group'], expected) + self.assertEqual(len(actual), 1) else: assert actual == iprops[name]