LBaaS: add status field to PoolMonitorAssociation table

also fixes branch in migrations

Fixes bug 1166395

Change-Id: I451603cf152d84c750edb6fb1da59b4c7563cbce
This commit is contained in:
Oleg Bondarev 2013-07-10 18:08:35 +04:00
parent 335f4f0366
commit 2d4821c8c0
7 changed files with 132 additions and 21 deletions

View File

@ -152,7 +152,8 @@ class HealthMonitor(model_base.BASEV2, models_v2.HasId, models_v2.HasTenant,
)
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),
@ -568,7 +569,8 @@ class LoadBalancerPluginDb(LoadBalancerPluginBase,
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']]
@ -577,19 +579,25 @@ class LoadBalancerPluginDb(LoadBalancerPluginBase,
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
@ -674,6 +682,7 @@ class LoadBalancerPluginDb(LoadBalancerPluginBase,
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'],
@ -684,7 +693,7 @@ class LoadBalancerPluginDb(LoadBalancerPluginBase,
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)

View File

@ -0,0 +1,63 @@
# 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')

View File

@ -49,6 +49,11 @@ class HealthMonitorNotFound(qexception.NotFound):
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")

View File

@ -131,6 +131,12 @@ class LoadBalancerAbstractDriver(object):
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

View File

@ -110,8 +110,8 @@ class LoadBalancerCallbacks(object):
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):
@ -137,7 +137,7 @@ class LoadBalancerCallbacks(object):
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

View File

@ -206,14 +206,13 @@ class LoadBalancerPlugin(loadbalancer_db.LoadBalancerPluginDb,
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)

View File

@ -832,7 +832,7 @@ class TestLoadBalancer(LoadBalancerPluginDbTestCase):
('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)
@ -916,7 +916,7 @@ class TestLoadBalancer(LoadBalancerPluginDbTestCase):
('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)
@ -1225,6 +1225,35 @@ class TestLoadBalancer(LoadBalancerPluginDbTestCase):
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'