primaryjoin="MeteringLabel.tenant_id==Router.tenant_id",
foreign_keys='MeteringLabel.tenant_id',
uselist=True)
+ shared = sa.Column(sa.Boolean, default=False, server_default=sql.false())
class MeteringDbMixin(metering.MeteringPluginBase,
res = {'id': metering_label['id'],
'name': metering_label['name'],
'description': metering_label['description'],
+ 'shared': metering_label['shared'],
'tenant_id': metering_label['tenant_id']}
return self._fields(res, fields)
metering_db = MeteringLabel(id=uuidutils.generate_uuid(),
description=m['description'],
tenant_id=tenant_id,
- name=m['name'])
+ name=m['name'],
+ shared=m['shared'])
context.session.add(metering_db)
return self._make_metering_label_dict(metering_db)
return res
- def _process_sync_metering_data(self, labels):
+ def _process_sync_metering_data(self, context, labels):
+ all_routers = None
+
routers_dict = {}
for label in labels:
- routers = label.routers
+ if label.shared:
+ if not all_routers:
+ all_routers = self._get_collection_query(context,
+ l3_db.Router)
+ routers = all_routers
+ else:
+ routers = label.routers
+
for router in routers:
router_dict = routers_dict.get(
router['id'],
labels = (labels.join(MeteringLabel.routers).
filter(l3_db.Router.id.in_(router_ids)))
- return self._process_sync_metering_data(labels)
+ return self._process_sync_metering_data(context, labels)
--- /dev/null
+# Copyright 2014 OpenStack Foundation
+#
+# 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.
+#
+
+"""metering_label_shared
+
+Revision ID: 3c346828361e
+Revises: 16a27a58e093
+Create Date: 2014-08-27 15:03:46.537290
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '3c346828361e'
+down_revision = '16a27a58e093'
+
+from alembic import op
+import sqlalchemy as sa
+
+
+def upgrade(active_plugins=None, options=None):
+ op.add_column('meteringlabels', sa.Column('shared', sa.Boolean(),
+ server_default=sa.sql.false(),
+ nullable=True))
+
+
+def downgrade(active_plugins=None, options=None):
+ op.drop_column('meteringlabels', 'shared')
-16a27a58e093
+3c346828361e
'id': {'allow_post': False, 'allow_put': False,
'is_visible': True,
'primary_key': True},
- 'name': {'allow_post': True, 'allow_put': True,
+ 'name': {'allow_post': True, 'allow_put': False,
'is_visible': True, 'default': ''},
- 'description': {'allow_post': True, 'allow_put': True,
+ 'description': {'allow_post': True, 'allow_put': False,
'is_visible': True, 'default': ''},
'tenant_id': {'allow_post': True, 'allow_put': False,
'required_by_policy': True,
- 'is_visible': True}
+ 'is_visible': True},
+ 'shared': {'allow_post': True, 'allow_put': False,
+ 'is_visible': True, 'default': False,
+ 'convert_to': attr.convert_to_boolean}
},
'metering_label_rules': {
'id': {'allow_post': False, 'allow_put': False,
'metering_label_id': {'allow_post': True, 'allow_put': False,
'validate': {'type:uuid': None},
'is_visible': True, 'required_by_policy': True},
- 'direction': {'allow_post': True, 'allow_put': True,
+ 'direction': {'allow_post': True, 'allow_put': False,
'is_visible': True,
'validate': {'type:values': ['ingress', 'egress']}},
- 'excluded': {'allow_post': True, 'allow_put': True,
+ 'excluded': {'allow_post': True, 'allow_put': False,
'is_visible': True, 'default': False,
'convert_to': attr.convert_to_boolean},
'remote_ip_prefix': {'allow_post': True, 'allow_put': False,
data = {'metering_label': {'name': name,
'tenant_id': kwargs.get('tenant_id',
'test-tenant'),
+ 'shared': kwargs.get('shared', False),
'description': description}}
req = self.new_create_request('metering-labels', data,
fmt)
for k, v, in keys:
self.assertEqual(metering_label['metering_label'][k], v)
+ def test_create_metering_label_shared(self):
+ name = 'my label'
+ description = 'my metering label'
+ shared = True
+ keys = [('name', name,), ('description', description),
+ ('shared', shared)]
+ with self.metering_label(name, description,
+ shared=shared) as metering_label:
+ for k, v, in keys:
+ self.assertEqual(metering_label['metering_label'][k], v)
+
def test_delete_metering_label(self):
name = 'my label'
description = 'my metering label'
set_context=True):
self.mock_fanout.assert_called_with(self.ctx, expected)
+ def test_add_metering_label_shared_rpc_call(self):
+ second_uuid = 'e27fe2df-376e-4ac7-ae13-92f050a21f84'
+ expected = {'args': {'routers': [{'status': 'ACTIVE',
+ 'name': 'router1',
+ 'gw_port_id': None,
+ 'admin_state_up': True,
+ 'tenant_id': self.tenant_id,
+ '_metering_labels': [
+ {'rules': [],
+ 'id': self.uuid},
+ {'rules': [],
+ 'id': second_uuid}],
+ 'id': self.uuid}]},
+ 'namespace': None,
+ 'method': 'add_metering_label'}
+
+ tenant_id_2 = '8a268a58-1610-4890-87e0-07abb8231206'
+ with self.router(name='router1', tenant_id=self.tenant_id,
+ set_context=True):
+ with self.metering_label(tenant_id=self.tenant_id,
+ set_context=True):
+ self.mock_uuid.return_value = second_uuid
+ with self.metering_label(tenant_id=tenant_id_2, shared=True,
+ set_context=True):
+ self.mock_fanout.assert_called_with(self.ctx, expected)
+
def test_remove_metering_label_rpc_call(self):
expected = {'args':
{'routers': [{'status': 'ACTIVE',
self.meter_plugin = manager.NeutronManager.get_service_plugins().get(
constants.METERING)
+ self.tenant_id = 'admin_tenant_id'
+ self.tenant_id_1 = 'tenant_id_1'
+ self.tenant_id_2 = 'tenant_id_2'
+
self.adminContext = context.get_admin_context()
self._register_l3_agent('agent1')
self._remove_external_gateway_from_router(
r['id'], s['network_id'])
+
+ def test_get_sync_data_metering_shared(self):
+ with self.router(name='router1', tenant_id=self.tenant_id_1):
+ with self.router(name='router2', tenant_id=self.tenant_id_2):
+ with self.metering_label(tenant_id=self.tenant_id,
+ shared=True):
+ callbacks = metering_rpc.MeteringRpcCallbacks(
+ self.meter_plugin)
+ data = callbacks.get_sync_data_metering(self.adminContext)
+
+ routers = [router['name'] for router in data]
+
+ self.assertIn('router1', routers)
+ self.assertIn('router2', routers)
+
+ def test_get_sync_data_metering_not_shared(self):
+ with self.router(name='router1', tenant_id=self.tenant_id_1):
+ with self.router(name='router2', tenant_id=self.tenant_id_2):
+ with self.metering_label(tenant_id=self.tenant_id):
+ callbacks = metering_rpc.MeteringRpcCallbacks(
+ self.meter_plugin)
+ data = callbacks.get_sync_data_metering(self.adminContext)
+
+ routers = [router['name'] for router in data]
+
+ self.assertEqual([], routers)