diff --git a/swift/common/db.py b/swift/common/db.py index 783e00dd5c..8683d4e088 100644 --- a/swift/common/db.py +++ b/swift/common/db.py @@ -899,14 +899,24 @@ class ContainerBroker(DatabaseBroker): metadata = '' if include_metadata: metadata = ', metadata' - data = conn.execute(''' - SELECT account, container, created_at, put_timestamp, - delete_timestamp, object_count, bytes_used, - reported_put_timestamp, reported_delete_timestamp, - reported_object_count, reported_bytes_used, hash, id - %s - FROM container_stat - ''' % metadata).fetchone() + try: + data = conn.execute(''' + SELECT account, container, created_at, put_timestamp, + delete_timestamp, object_count, bytes_used, + reported_put_timestamp, reported_delete_timestamp, + reported_object_count, reported_bytes_used, hash, id + %s + FROM container_stat + ''' % metadata).fetchone() + except sqlite3.OperationalError, err: + if 'no such column: metadata' not in str(err): + raise + data = conn.execute(''' + SELECT account, container, created_at, put_timestamp, + delete_timestamp, object_count, bytes_used, + reported_put_timestamp, reported_delete_timestamp, + reported_object_count, reported_bytes_used, hash, id + FROM container_stat''').fetchone() data = dict(data) if include_metadata: try: diff --git a/swift/stats/db_stats_collector.py b/swift/stats/db_stats_collector.py index f65c20c3e2..95efaa8597 100644 --- a/swift/stats/db_stats_collector.py +++ b/swift/stats/db_stats_collector.py @@ -58,10 +58,10 @@ class DatabaseStatsCollector(Daemon): (self.stats_type, (time.time() - start) / 60)) def get_data(self): - raise Exception('Not Implemented') + raise NotImplementedError('Subclasses must override') def get_header(self): - raise Exception('Not Implemented') + raise NotImplementedError('Subclasses must override') def find_and_process(self): src_filename = time.strftime(self.filename_format) diff --git a/test/unit/stats/test_db_stats_collector.py b/test/unit/stats/test_db_stats_collector.py index d336016e77..3c4949aff5 100644 --- a/test/unit/stats/test_db_stats_collector.py +++ b/test/unit/stats/test_db_stats_collector.py @@ -93,7 +93,32 @@ class TestDbStats(unittest.TestCase): self.assertEqual(len(output_data), 10) return stat, output_data - def _gen_container_stat(self, set_metadata=False): + def _drop_metadata_col(self, broker, acc_name): + broker.conn.execute('''drop table container_stat''') + broker.conn.executescript(""" + CREATE TABLE container_stat ( + account TEXT DEFAULT '%s', + container TEXT DEFAULT 'test_con', + created_at TEXT, + put_timestamp TEXT DEFAULT '0', + delete_timestamp TEXT DEFAULT '0', + object_count INTEGER, + bytes_used INTEGER, + reported_put_timestamp TEXT DEFAULT '0', + reported_delete_timestamp TEXT DEFAULT '0', + reported_object_count INTEGER DEFAULT 0, + reported_bytes_used INTEGER DEFAULT 0, + hash TEXT default '00000000000000000000000000000000', + id TEXT, + status TEXT DEFAULT '', + status_changed_at TEXT DEFAULT '0' + ); + + INSERT INTO container_stat (object_count, bytes_used) + VALUES (1, 10); + """ % acc_name) + + def _gen_container_stat(self, set_metadata=False, drop_metadata=False): if set_metadata: self.conf['metadata_keys'] = 'test1,test2' # webob runs title on all headers @@ -116,8 +141,13 @@ class TestDbStats(unittest.TestCase): metadata_output = ',,1' # this will "commit" the data cont_db.get_info() - output_data.add('''"test_acc_%s","test_con",1,10%s''' % - (i, metadata_output)) + if drop_metadata: + output_data.add('''"test_acc_%s","test_con",1,10,,''' % i) + else: + output_data.add('''"test_acc_%s","test_con",1,10%s''' % + (i, metadata_output)) + if drop_metadata: + self._drop_metadata_col(cont_db, 'test_acc_%s' % i) self.assertEqual(len(output_data), 10) return stat, output_data @@ -147,6 +177,21 @@ class TestDbStats(unittest.TestCase): self.assertEqual(len(output_data), 0) + def test_account_stat_run_once_container_no_metadata(self): + + stat, output_data = self._gen_container_stat(set_metadata=True, + drop_metadata=True) + stat.run_once() + stat_file = os.listdir(self.log_dir)[0] + with open(os.path.join(self.log_dir, stat_file)) as stat_handle: + headers = stat_handle.readline() + self.assert_(headers.startswith('Account Hash,Container Name,')) + for i in range(10): + data = stat_handle.readline() + output_data.discard(data.strip()) + + self.assertEqual(len(output_data), 0) + def test_account_stat_run_once_both(self): acc_stat, acc_output_data = self._gen_account_stat() con_stat, con_output_data = self._gen_container_stat() @@ -180,8 +225,8 @@ class TestDbStats(unittest.TestCase): def test_not_implemented(self): db_stat = db_stats_collector.DatabaseStatsCollector(self.conf, 'account', 'test_dir', 'stats-%Y%m%d%H_') - self.assertRaises(Exception, db_stat.get_data) - self.assertRaises(Exception, db_stat.get_header) + self.assertRaises(NotImplementedError, db_stat.get_data) + self.assertRaises(NotImplementedError, db_stat.get_header) def test_not_not_mounted(self): self.conf['mount_check'] = 'true'