Skip to content

Commit

Permalink
Change the column counter_volume to Float
Browse files Browse the repository at this point in the history
counter_volume was previously an Integer (32 bits value in SQL
implementations as MySQL or PostgreSQL) and limited in values from
-2147483648 to 2147483647, very small for things like disk I/O bytes,
network I/O bytes, image size, object size, volume size, …
Furthermore one might want to store some real numbers (ℝ) (temperatures,
power comsumption, …)

Change-Id: Ifdb8e8e84e8e01df267d71bc72cdc3f56bb2f695
Fixes: bug #1158276
  • Loading branch information
fcharlier committed Mar 26, 2013
1 parent 86ebece commit d09b7b7
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 2 deletions.
@@ -0,0 +1,32 @@
# -*- encoding: utf-8 -*-
#
# Copyright © 2013 eNovance SAS <licensing@enovance.com>
# Author: François Charlier <francois.charlier@enovance.com>
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from sqlalchemy import *

meta = MetaData()


def upgrade(migrate_engine):
meta.bind = migrate_engine
meter = Table('meter', meta, autoload=True)
meter.c.counter_volume.alter(type=Float(53))


def downgrade(migrate_engine):
meta.bind = migrate_engine
meter = Table('meter', meta, autoload=True)
meter.c.counter_volume.alter(type=Integer)
5 changes: 3 additions & 2 deletions ceilometer/storage/sqlalchemy/models.py
Expand Up @@ -22,7 +22,8 @@
import urlparse

from oslo.config import cfg
from sqlalchemy import Column, Integer, String, Table, ForeignKey, DateTime
from sqlalchemy import Column, Integer, String, Table, ForeignKey, DateTime, \
Float
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy.types import TypeDecorator, VARCHAR
Expand Down Expand Up @@ -108,7 +109,7 @@ class Meter(Base):
resource_metadata = Column(JSONEncodedDict)
counter_type = Column(String(255))
counter_unit = Column(String(255))
counter_volume = Column(Integer)
counter_volume = Column(Float(53))
timestamp = Column(DateTime, default=timeutils.utcnow)
message_signature = Column(String)
message_id = Column(String)
Expand Down
79 changes: 79 additions & 0 deletions tests/storage/base.py
Expand Up @@ -878,3 +878,82 @@ def test_one_resource(self):
assert results['max'] == 7
assert results['sum'] == 18
assert results['avg'] == 6


class CounterDataTypeTest(DBTestBase):

def prepare_data(self):
c = counter.Counter(
'dummyBigCounter',
counter.TYPE_CUMULATIVE,
unit='',
volume=3372036854775807,
user_id='user-id',
project_id='project-id',
resource_id='resource-id',
timestamp=datetime.datetime(2012, 7, 2, 10, 40),
resource_metadata={}
)
msg = meter.meter_message_from_counter(
c,
cfg.CONF.metering_secret,
'test-1',
)

self.conn.record_metering_data(msg)

c = counter.Counter(
'dummySmallCounter',
counter.TYPE_CUMULATIVE,
unit='',
volume=-3372036854775807,
user_id='user-id',
project_id='project-id',
resource_id='resource-id',
timestamp=datetime.datetime(2012, 7, 2, 10, 40),
resource_metadata={}
)
msg = meter.meter_message_from_counter(
c,
cfg.CONF.metering_secret,
'test-1',
)
self.conn.record_metering_data(msg)

c = counter.Counter(
'floatCounter',
counter.TYPE_CUMULATIVE,
unit='',
volume=1938495037.53697,
user_id='user-id',
project_id='project-id',
resource_id='resource-id',
timestamp=datetime.datetime(2012, 7, 2, 10, 40),
resource_metadata={}
)
msg = meter.meter_message_from_counter(
c,
cfg.CONF.metering_secret,
'test-1',
)
self.conn.record_metering_data(msg)

def test_storage_can_handle_large_values(self):
f = storage.EventFilter(
meter='dummyBigCounter',
)
results = list(self.conn.get_samples(f))
self.assertEqual(results[0]['counter_volume'], 3372036854775807)

f = storage.EventFilter(
meter='dummySmallCounter',
)
results = list(self.conn.get_samples(f))
self.assertEqual(results[0]['counter_volume'], -3372036854775807)

def test_storage_can_handle_float_values(self):
f = storage.EventFilter(
meter='floatCounter',
)
results = list(self.conn.get_samples(f))
self.assertEqual(results[0]['counter_volume'], 1938495037.53697)
4 changes: 4 additions & 0 deletions tests/storage/test_impl_hbase.py
Expand Up @@ -177,6 +177,10 @@ class StatisticsTest(base.StatisticsTest, HBaseEngineTestBase):
pass


class CounterDataTypeTest(base.CounterDataTypeTest, HBaseEngineTestBase):
pass


###############
# This is a very crude version of "in-memory HBase", which implements just
# enough functionality of HappyBase API to support testing of our driver.
Expand Down
4 changes: 4 additions & 0 deletions tests/storage/test_impl_mongodb.py
Expand Up @@ -226,3 +226,7 @@ def old_record_metering_data(self, data):
def test_counter_unit(self):
meters = list(self.conn.get_meters())
self.assertEqual(len(meters), 1)


class CounterDataTypeTest(base.CounterDataTypeTest, MongoDBEngineTestBase):
pass
4 changes: 4 additions & 0 deletions tests/storage/test_impl_sqlalchemy.py
Expand Up @@ -135,6 +135,10 @@ class StatisticsTest(base.StatisticsTest, SQLAlchemyEngineTestBase):
pass


class CounterDataTypeTest(base.CounterDataTypeTest, SQLAlchemyEngineTestBase):
pass


def test_model_table_args():
cfg.CONF.database_connection = 'mysql://localhost'
assert table_args()

0 comments on commit d09b7b7

Please sign in to comment.