diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..16fa618c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,14 @@ +language: python +python: + - "2.7" + +install: + - pip install tox + +script: + - tox + +env: + - TOXENV=py27 + - TOXENV=pep8 + - TOXENV=coveralls diff --git a/README.md b/README.md index 127e37ec..5283fb12 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -#caso +# caso [![Build Status](https://travis-ci.org/IFCA/caso)](https://travis-ci.org/IFCA/caso) cASO is an OpenStack Accounting extractor. diff --git a/caso/extract/ceilometer.py b/caso/extract/ceilometer.py index f57f77a1..0baea194 100644 --- a/caso/extract/ceilometer.py +++ b/caso/extract/ceilometer.py @@ -18,6 +18,7 @@ import ceilometerclient.client import dateutil.parser +from dateutil import tz import glanceclient.client from oslo.config import cfg @@ -156,7 +157,8 @@ def _build_record(self, instance, users, vo, images, now): return r def extract_for_tenant(self, tenant, lastrun): - now = datetime.datetime.now().replace(tzinfo=None) + now = datetime.datetime.now(tz.tzutc()) + now.replace(tzinfo=None) # Try and except here # Getting clients diff --git a/caso/extract/manager.py b/caso/extract/manager.py index 44552f06..aabfab6e 100644 --- a/caso/extract/manager.py +++ b/caso/extract/manager.py @@ -15,6 +15,7 @@ # under the License. import dateutil.parser +from dateutil import tz from oslo.config import cfg from oslo.utils import importutils import six @@ -38,7 +39,8 @@ cfg.StrOpt('extract_from', help='Extract records from this date. If it is not set, ' 'extract records from last run. If none are set, extract ' - 'records from the beginning of time.'), + 'records from the beginning of time. If no time zone is ' + 'specified, UTC will be used.'), cfg.StrOpt('extractor', choices=SUPPORTED_EXTRACTORS, default='nova', @@ -75,8 +77,11 @@ def _extract(self, extract_from): def get_records(self, lastrun="1970-01-01"): extract_from = CONF.extract_from or lastrun - if isinstance(extract_from, six.text_type): + if isinstance(extract_from, six.string_types): extract_from = dateutil.parser.parse(extract_from) + + if extract_from.tzinfo is None: + extract_from.replace(tzinfo=tz.tzutc()) if self.records is None: self._extract(extract_from) return self.records diff --git a/caso/extract/nova.py b/caso/extract/nova.py index 263ca827..d39c7013 100644 --- a/caso/extract/nova.py +++ b/caso/extract/nova.py @@ -17,6 +17,7 @@ import datetime import dateutil.parser +from dateutil import tz import novaclient.client from oslo.config import cfg @@ -45,7 +46,11 @@ def _get_conn(self, tenant): return conn def extract_for_tenant(self, tenant, lastrun): - now = datetime.datetime.now() + # Some API calls do not expect a TZ, so we have to remove the timezone + # from the dates. We assume that all dates coming from upstream are + # in UTC TZ. + lastrun = lastrun.replace(tzinfo=None) + now = datetime.datetime.now(tz.tzutc()).replace(tzinfo=None) end = now + datetime.timedelta(days=1) # Try and except here diff --git a/caso/manager.py b/caso/manager.py index 7dd78c4e..728a0f6f 100644 --- a/caso/manager.py +++ b/caso/manager.py @@ -18,6 +18,7 @@ import os.path import dateutil.parser +from dateutil import tz from oslo.config import cfg import caso.extract.manager @@ -71,4 +72,4 @@ def run(self): if not CONF.dry_run: self.messenger.push_to_all(records) with open(self.last_run_file, "w") as fd: - fd.write(str(datetime.datetime.now())) + fd.write(str(datetime.datetime.now(tz.tzutc()))) diff --git a/caso/messenger/ssm.py b/caso/messenger/ssm.py index a8c49a77..fe1579d7 100644 --- a/caso/messenger/ssm.py +++ b/caso/messenger/ssm.py @@ -40,6 +40,9 @@ def __init__(self): utils.makedirs(CONF.ssm.output_path) def push(self, records): + if not records: + return + entries = [] for _, record in records.iteritems(): aux = "" diff --git a/caso/tests/test_manager.py b/caso/tests/test_manager.py index 6169705d..8139a101 100644 --- a/caso/tests/test_manager.py +++ b/caso/tests/test_manager.py @@ -18,9 +18,10 @@ import contextlib import datetime -import StringIO +from dateutil import tz import mock +import six from caso import manager from caso.tests import base @@ -53,7 +54,7 @@ def test_lastrun_does_not_exist(self): def test_lastrun_exists(self): expected = datetime.datetime(2014, 12, 10, 13, 10, 26, 664598) - aux = StringIO.StringIO(expected) + aux = six.StringIO(expected) with contextlib.nested( mock.patch("os.path.exists"), @@ -66,7 +67,7 @@ def test_lastrun_exists(self): self.assertEqual(expected, self.manager.lastrun) def test_lastrun_is_invalid(self): - aux = StringIO.StringIO("foo") + aux = six.StringIO("foo") # NOTE(aloga): manager.lastrun is a property, so we need to # create our own callable here. @@ -89,7 +90,7 @@ def test_dry_run(self): # https://code.google.com/p/mock/issues/detail?id=117 with mock.patch("caso.manager.Manager.lastrun", new_callable=mock.PropertyMock) as lastrun: - lastrun.return_value = datetime.datetime.now() + lastrun.return_value = datetime.datetime.now(tz.tzutc()) mngr = manager.Manager() mngr.messenger.push_to_all.assert_not_called() mngr.run() diff --git a/requirements.txt b/requirements.txt index 97429061..0837a8a4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,9 +6,9 @@ six python-novaclient python-keystoneclient -python-dateutil python-glanceclient python-ceilometerclient dirq +python-dateutil diff --git a/tox.ini b/tox.ini index 1a4e94b1..847027f3 100644 --- a/tox.ini +++ b/tox.ini @@ -22,6 +22,12 @@ commands = {posargs} [testenv:cover] commands = python setup.py testr --coverage --testr-args='{posargs}' +[testenv:coveralls] +commands = python setup.py testr --coverage --testr-args='{posargs}' + coveralls +deps = coveralls + {[testenv]deps} + [testenv:docs] commands = python setup.py build_sphinx