)
-class PoolMonitorAssociation(model_base.BASEV2):
+class PoolMonitorAssociation(model_base.BASEV2,
+ models_v2.HasStatusDescription):
"""Many-to-many association between pool and healthMonitor classes."""
pool_id = sa.Column(sa.String(36),
pool = self._get_resource(context, Pool, pool_id)
assoc = PoolMonitorAssociation(pool_id=pool_id,
- monitor_id=monitor_id)
+ monitor_id=monitor_id,
+ status=constants.PENDING_CREATE)
pool.monitors.append(assoc)
monitors = [monitor['monitor_id'] for monitor in pool['monitors']]
def delete_pool_health_monitor(self, context, id, pool_id):
with context.session.begin(subtransactions=True):
+ assoc = self.get_pool_health_monitor(context, id, pool_id)
pool = self._get_resource(context, Pool, pool_id)
- try:
- monitor_qry = context.session.query(PoolMonitorAssociation)
- monitor = monitor_qry.filter_by(monitor_id=id,
- pool_id=pool_id).one()
- pool.monitors.remove(monitor)
- except exc.NoResultFound:
- raise loadbalancer.HealthMonitorNotFound(monitor_id=id)
+ pool.monitors.remove(assoc)
def get_pool_health_monitor(self, context, id, pool_id, fields=None):
- # TODO(markmcclain) look into why pool_id is ignored
- healthmonitor = self._get_resource(context, HealthMonitor, id)
- return self._make_health_monitor_dict(healthmonitor, fields)
+ try:
+ assoc_qry = context.session.query(PoolMonitorAssociation)
+ return assoc_qry.filter_by(monitor_id=id, pool_id=pool_id).one()
+ except exc.NoResultFound:
+ raise loadbalancer.PoolMonitorAssociationNotFound(
+ monitor_id=id, pool_id=pool_id)
+
+ def update_pool_health_monitor(self, context, id, pool_id,
+ status, status_description=None):
+ with context.session.begin(subtransactions=True):
+ assoc = self.get_pool_health_monitor(context, id, pool_id)
+ self.assert_modification_allowed(assoc)
+ assoc.status = status
+ assoc.status_description = status_description
########################################################
# Member DB access
v = health_monitor['health_monitor']
tenant_id = self._get_tenant_id_for_create(context, v)
with context.session.begin(subtransactions=True):
+ # setting ACTIVE status sinse healthmon is shared DB object
monitor_db = HealthMonitor(id=uuidutils.generate_uuid(),
tenant_id=tenant_id,
type=v['type'],
url_path=v['url_path'],
expected_codes=v['expected_codes'],
admin_state_up=v['admin_state_up'],
- status=constants.PENDING_CREATE)
+ status=constants.ACTIVE)
context.session.add(monitor_db)
return self._make_health_monitor_dict(monitor_db)
--- /dev/null
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+#
+# Copyright 2013 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.
+#
+
+"""Pool Monitor status field
+
+Revision ID: 11c6e18605c8
+Revises: 39cf3f799352
+Create Date: 2013-07-10 06:07:20.878520
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '11c6e18605c8'
+down_revision = '39cf3f799352'
+
+# Change to ['*'] if this migration applies to all plugins
+
+migration_for_plugins = ['*']
+
+from alembic import op
+import sqlalchemy as sa
+
+from neutron.db import migration
+
+
+# Change to ['*'] if this migration applies to all plugins
+migration_for_plugins = ['*']
+
+
+def upgrade(active_plugin=None, options=None):
+ if not migration.should_run(active_plugin, migration_for_plugins):
+ return
+
+ op.add_column('poolmonitorassociations', sa.Column('status',
+ sa.String(16),
+ nullable=False))
+ op.add_column('poolmonitorassociations', sa.Column('status_description',
+ sa.String(255)))
+
+ # Set status to ACTIVE for existing associations
+ op.execute("UPDATE poolmonitorassociations SET status='ACTIVE'")
+
+
+def downgrade(active_plugin=None, options=None):
+ if not migration.should_run(active_plugin, migration_for_plugins):
+ return
+
+ op.drop_column('poolmonitorassociations', 'status')
+ op.drop_column('poolmonitorassociations', 'status_description')
message = _("Health_monitor %(monitor_id)s could not be found")
+class PoolMonitorAssociationNotFound(qexception.NotFound):
+ message = _("Monitor %(monitor_id)s is not associated "
+ "with Pool %(pool_id)s")
+
+
class StateInvalid(qexception.NeutronException):
message = _("Invalid state %(state)s of Loadbalancer resource %(id)s")
def create_pool_health_monitor(self, context,
health_monitor,
pool_id):
+ """Driver may call the code below in order to update the status.
+ self.plugin.update_pool_health_monitor(context,
+ health_monitor["id"],
+ pool_id,
+ constants.ACTIVE)
+ """
pass
@abc.abstractmethod
m.status = constants.ACTIVE
for hm in pool.monitors:
- if hm.healthmonitor.status in ACTIVE_PENDING:
- hm.healthmonitor.status = constants.ACTIVE
+ if hm.status in ACTIVE_PENDING:
+ hm.status = constants.ACTIVE
if (pool.status != constants.ACTIVE
or pool.vip.status != constants.ACTIVE):
retval['healthmonitors'] = [
self.plugin._make_health_monitor_dict(hm.healthmonitor)
for hm in pool.monitors
- if hm.healthmonitor.status == constants.ACTIVE
+ if hm.status == constants.ACTIVE
]
return retval
health_monitor,
pool_id
)
- # open issue: PoolMonitorAssociation has no status field
- # so we cant set the status to pending and let the driver
- # set the real status of the association
self.driver.create_pool_health_monitor(
context, health_monitor, pool_id)
return retval
def delete_pool_health_monitor(self, context, id, pool_id):
+ self.update_pool_health_monitor(context, id, pool_id,
+ constants.PENDING_DELETE)
hm = self.get_health_monitor(context, id)
self.driver.delete_pool_health_monitor(
context, hm, pool_id)
('timeout', 10),
('max_retries', 3),
('admin_state_up', True),
- ('status', 'PENDING_CREATE')]
+ ('status', 'ACTIVE')]
with self.health_monitor() as monitor:
for k, v in keys:
self.assertEqual(monitor['health_monitor'][k], v)
('timeout', 10),
('max_retries', 3),
('admin_state_up', True),
- ('status', 'PENDING_CREATE')]
+ ('status', 'ACTIVE')]
req = self.new_show_request('health_monitors',
monitor['health_monitor']['id'],
fmt=self.fmt)
self.assertEqual(updated_pool['status'], 'ACTIVE')
self.assertFalse(pool['pool']['status_description'])
+ def test_update_pool_health_monitor(self):
+ with self.pool() as pool:
+ with self.health_monitor() as hm:
+ res = self.plugin.create_pool_health_monitor(
+ context.get_admin_context(),
+ hm, pool['pool']['id'])
+ self.assertEqual({'health_monitor':
+ [hm['health_monitor']['id']]},
+ res)
+
+ assoc = self.plugin.get_pool_health_monitor(
+ context.get_admin_context(),
+ hm['health_monitor']['id'],
+ pool['pool']['id'])
+ self.assertEqual(assoc['status'], 'PENDING_CREATE')
+ self.assertIsNone(assoc['status_description'])
+
+ self.plugin.update_pool_health_monitor(
+ context.get_admin_context(),
+ hm['health_monitor']['id'],
+ pool['pool']['id'],
+ 'ACTIVE', 'ok')
+ assoc = self.plugin.get_pool_health_monitor(
+ context.get_admin_context(),
+ hm['health_monitor']['id'],
+ pool['pool']['id'])
+ self.assertEqual(assoc['status'], 'ACTIVE')
+ self.assertEqual(assoc['status_description'], 'ok')
+
class TestLoadBalancerXML(TestLoadBalancer):
fmt = 'xml'