LBaaS: add status field to PoolMonitorAssociation table
also fixes branch in migrations Fixes bug 1166395 Change-Id: I451603cf152d84c750edb6fb1da59b4c7563cbce
This commit is contained in:
parent
335f4f0366
commit
2d4821c8c0
@ -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."""
|
"""Many-to-many association between pool and healthMonitor classes."""
|
||||||
|
|
||||||
pool_id = sa.Column(sa.String(36),
|
pool_id = sa.Column(sa.String(36),
|
||||||
@ -568,7 +569,8 @@ class LoadBalancerPluginDb(LoadBalancerPluginBase,
|
|||||||
pool = self._get_resource(context, Pool, pool_id)
|
pool = self._get_resource(context, Pool, pool_id)
|
||||||
|
|
||||||
assoc = PoolMonitorAssociation(pool_id=pool_id,
|
assoc = PoolMonitorAssociation(pool_id=pool_id,
|
||||||
monitor_id=monitor_id)
|
monitor_id=monitor_id,
|
||||||
|
status=constants.PENDING_CREATE)
|
||||||
pool.monitors.append(assoc)
|
pool.monitors.append(assoc)
|
||||||
monitors = [monitor['monitor_id'] for monitor in pool['monitors']]
|
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):
|
def delete_pool_health_monitor(self, context, id, pool_id):
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
|
assoc = self.get_pool_health_monitor(context, id, pool_id)
|
||||||
pool = self._get_resource(context, Pool, pool_id)
|
pool = self._get_resource(context, Pool, pool_id)
|
||||||
try:
|
pool.monitors.remove(assoc)
|
||||||
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)
|
|
||||||
|
|
||||||
def get_pool_health_monitor(self, context, id, pool_id, fields=None):
|
def get_pool_health_monitor(self, context, id, pool_id, fields=None):
|
||||||
# TODO(markmcclain) look into why pool_id is ignored
|
try:
|
||||||
healthmonitor = self._get_resource(context, HealthMonitor, id)
|
assoc_qry = context.session.query(PoolMonitorAssociation)
|
||||||
return self._make_health_monitor_dict(healthmonitor, fields)
|
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
|
# Member DB access
|
||||||
@ -674,6 +682,7 @@ class LoadBalancerPluginDb(LoadBalancerPluginBase,
|
|||||||
v = health_monitor['health_monitor']
|
v = health_monitor['health_monitor']
|
||||||
tenant_id = self._get_tenant_id_for_create(context, v)
|
tenant_id = self._get_tenant_id_for_create(context, v)
|
||||||
with context.session.begin(subtransactions=True):
|
with context.session.begin(subtransactions=True):
|
||||||
|
# setting ACTIVE status sinse healthmon is shared DB object
|
||||||
monitor_db = HealthMonitor(id=uuidutils.generate_uuid(),
|
monitor_db = HealthMonitor(id=uuidutils.generate_uuid(),
|
||||||
tenant_id=tenant_id,
|
tenant_id=tenant_id,
|
||||||
type=v['type'],
|
type=v['type'],
|
||||||
@ -684,7 +693,7 @@ class LoadBalancerPluginDb(LoadBalancerPluginBase,
|
|||||||
url_path=v['url_path'],
|
url_path=v['url_path'],
|
||||||
expected_codes=v['expected_codes'],
|
expected_codes=v['expected_codes'],
|
||||||
admin_state_up=v['admin_state_up'],
|
admin_state_up=v['admin_state_up'],
|
||||||
status=constants.PENDING_CREATE)
|
status=constants.ACTIVE)
|
||||||
context.session.add(monitor_db)
|
context.session.add(monitor_db)
|
||||||
return self._make_health_monitor_dict(monitor_db)
|
return self._make_health_monitor_dict(monitor_db)
|
||||||
|
|
||||||
|
@ -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')
|
@ -49,6 +49,11 @@ class HealthMonitorNotFound(qexception.NotFound):
|
|||||||
message = _("Health_monitor %(monitor_id)s could not be found")
|
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):
|
class StateInvalid(qexception.NeutronException):
|
||||||
message = _("Invalid state %(state)s of Loadbalancer resource %(id)s")
|
message = _("Invalid state %(state)s of Loadbalancer resource %(id)s")
|
||||||
|
|
||||||
|
@ -131,6 +131,12 @@ class LoadBalancerAbstractDriver(object):
|
|||||||
def create_pool_health_monitor(self, context,
|
def create_pool_health_monitor(self, context,
|
||||||
health_monitor,
|
health_monitor,
|
||||||
pool_id):
|
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
|
pass
|
||||||
|
|
||||||
@abc.abstractmethod
|
@abc.abstractmethod
|
||||||
|
@ -110,8 +110,8 @@ class LoadBalancerCallbacks(object):
|
|||||||
m.status = constants.ACTIVE
|
m.status = constants.ACTIVE
|
||||||
|
|
||||||
for hm in pool.monitors:
|
for hm in pool.monitors:
|
||||||
if hm.healthmonitor.status in ACTIVE_PENDING:
|
if hm.status in ACTIVE_PENDING:
|
||||||
hm.healthmonitor.status = constants.ACTIVE
|
hm.status = constants.ACTIVE
|
||||||
|
|
||||||
if (pool.status != constants.ACTIVE
|
if (pool.status != constants.ACTIVE
|
||||||
or pool.vip.status != constants.ACTIVE):
|
or pool.vip.status != constants.ACTIVE):
|
||||||
@ -137,7 +137,7 @@ class LoadBalancerCallbacks(object):
|
|||||||
retval['healthmonitors'] = [
|
retval['healthmonitors'] = [
|
||||||
self.plugin._make_health_monitor_dict(hm.healthmonitor)
|
self.plugin._make_health_monitor_dict(hm.healthmonitor)
|
||||||
for hm in pool.monitors
|
for hm in pool.monitors
|
||||||
if hm.healthmonitor.status == constants.ACTIVE
|
if hm.status == constants.ACTIVE
|
||||||
]
|
]
|
||||||
|
|
||||||
return retval
|
return retval
|
||||||
|
@ -206,14 +206,13 @@ class LoadBalancerPlugin(loadbalancer_db.LoadBalancerPluginDb,
|
|||||||
health_monitor,
|
health_monitor,
|
||||||
pool_id
|
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(
|
self.driver.create_pool_health_monitor(
|
||||||
context, health_monitor, pool_id)
|
context, health_monitor, pool_id)
|
||||||
return retval
|
return retval
|
||||||
|
|
||||||
def delete_pool_health_monitor(self, context, id, pool_id):
|
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)
|
hm = self.get_health_monitor(context, id)
|
||||||
self.driver.delete_pool_health_monitor(
|
self.driver.delete_pool_health_monitor(
|
||||||
context, hm, pool_id)
|
context, hm, pool_id)
|
||||||
|
@ -832,7 +832,7 @@ class TestLoadBalancer(LoadBalancerPluginDbTestCase):
|
|||||||
('timeout', 10),
|
('timeout', 10),
|
||||||
('max_retries', 3),
|
('max_retries', 3),
|
||||||
('admin_state_up', True),
|
('admin_state_up', True),
|
||||||
('status', 'PENDING_CREATE')]
|
('status', 'ACTIVE')]
|
||||||
with self.health_monitor() as monitor:
|
with self.health_monitor() as monitor:
|
||||||
for k, v in keys:
|
for k, v in keys:
|
||||||
self.assertEqual(monitor['health_monitor'][k], v)
|
self.assertEqual(monitor['health_monitor'][k], v)
|
||||||
@ -916,7 +916,7 @@ class TestLoadBalancer(LoadBalancerPluginDbTestCase):
|
|||||||
('timeout', 10),
|
('timeout', 10),
|
||||||
('max_retries', 3),
|
('max_retries', 3),
|
||||||
('admin_state_up', True),
|
('admin_state_up', True),
|
||||||
('status', 'PENDING_CREATE')]
|
('status', 'ACTIVE')]
|
||||||
req = self.new_show_request('health_monitors',
|
req = self.new_show_request('health_monitors',
|
||||||
monitor['health_monitor']['id'],
|
monitor['health_monitor']['id'],
|
||||||
fmt=self.fmt)
|
fmt=self.fmt)
|
||||||
@ -1225,6 +1225,35 @@ class TestLoadBalancer(LoadBalancerPluginDbTestCase):
|
|||||||
self.assertEqual(updated_pool['status'], 'ACTIVE')
|
self.assertEqual(updated_pool['status'], 'ACTIVE')
|
||||||
self.assertFalse(pool['pool']['status_description'])
|
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):
|
class TestLoadBalancerXML(TestLoadBalancer):
|
||||||
fmt = 'xml'
|
fmt = 'xml'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user