from oslo.config import cfg
import sqlalchemy as sa
+from sqlalchemy import exc as sa_exc
from sqlalchemy import orm
from sqlalchemy.orm import exc
from sqlalchemy.sql import expression as expr
vip_db['id'])
vip_db.session_persistence = s_p
- context.session.add(vip_db)
- context.session.flush()
+ try:
+ context.session.add(vip_db)
+ context.session.flush()
+ except sa_exc.IntegrityError:
+ raise loadbalancer.VipExists(pool_id=v['pool_id'])
# create a port to reserve address for IPAM
self._create_port_for_vip(
self._delete_session_persistence(context, id)
if v:
- vip_db.update(v)
- # If the pool_id is changed, we need to update
- # the associated pools
- if 'pool_id' in v:
- new_pool = self._get_resource(context, Pool, v['pool_id'])
- self.assert_modification_allowed(new_pool)
-
- # check that the pool matches the tenant_id
- if new_pool['tenant_id'] != vip_db['tenant_id']:
- raise q_exc.NotAuthorized()
- # validate that the pool has same protocol
- if new_pool['protocol'] != vip_db['protocol']:
- raise loadbalancer.ProtocolMismatch(
- vip_proto=vip_db['protocol'],
- pool_proto=new_pool['protocol'])
-
- if vip_db['pool_id']:
- old_pool = self._get_resource(
- context,
- Pool,
- vip_db['pool_id']
- )
- old_pool['vip_id'] = None
-
- new_pool['vip_id'] = vip_db['id']
+ try:
+ # in case new pool already has a vip
+ # update will raise integrity error at first query
+ old_pool_id = vip_db['pool_id']
+ vip_db.update(v)
+ # If the pool_id is changed, we need to update
+ # the associated pools
+ if 'pool_id' in v:
+ new_pool = self._get_resource(context, Pool,
+ v['pool_id'])
+ self.assert_modification_allowed(new_pool)
+
+ # check that the pool matches the tenant_id
+ if new_pool['tenant_id'] != vip_db['tenant_id']:
+ raise q_exc.NotAuthorized()
+ # validate that the pool has same protocol
+ if new_pool['protocol'] != vip_db['protocol']:
+ raise loadbalancer.ProtocolMismatch(
+ vip_proto=vip_db['protocol'],
+ pool_proto=new_pool['protocol'])
+
+ if old_pool_id:
+ old_pool = self._get_resource(
+ context,
+ Pool,
+ old_pool_id
+ )
+ old_pool['vip_id'] = None
+
+ new_pool['vip_id'] = vip_db['id']
+ except sa_exc.IntegrityError:
+ raise loadbalancer.VipExists(pool_id=v['pool_id'])
return self._make_vip_dict(vip_db)
from oslo.config import cfg
import webob.exc
+from quantum import context
from quantum.api.extensions import ExtensionMiddleware
from quantum.api.extensions import PluginAwareExtensionManager
from quantum.api.v2 import attributes
from quantum.common import exceptions as q_exc
from quantum.common.test_lib import test_config
from quantum.db import api as db
+from quantum.db.loadbalancer import loadbalancer_db as ldb
import quantum.extensions
from quantum.extensions import loadbalancer
from quantum.manager import QuantumManager
self._subnet_id = "0c798ed8-33ba-11e2-8b28-000c291c4d14"
- plugin = loadbalancer_plugin.LoadBalancerPlugin()
+ self.plugin = loadbalancer_plugin.LoadBalancerPlugin()
ext_mgr = PluginAwareExtensionManager(
extensions_path,
- {constants.LOADBALANCER: plugin}
+ {constants.LOADBALANCER: self.plugin}
)
app = config.load_paste_app('extensions_test_app')
self.ext_api = ExtensionMiddleware(app, ext_mgr=ext_mgr)
)
return vip
+ def test_create_vip_twice_for_same_pool(self):
+ """ Test loadbalancer db plugin via extension and directly """
+ with self.subnet() as subnet:
+ with self.pool(name="pool1") as pool:
+ with self.vip(name='vip1', subnet=subnet, pool=pool) as vip:
+ vip_data = {
+ 'name': 'vip1',
+ 'pool_id': pool['pool']['id'],
+ 'description': '',
+ 'protocol_port': 80,
+ 'protocol': 'HTTP',
+ 'connection_limit': -1,
+ 'admin_state_up': True,
+ 'status': 'PENDING_CREATE',
+ 'tenant_id': self._tenant_id,
+ 'session_persistence': ''
+ }
+ self.assertRaises(loadbalancer.VipExists,
+ self.plugin.create_vip,
+ context.get_admin_context(),
+ {'vip': vip_data})
+
+ def test_update_vip_raises_vip_exists(self):
+ with self.subnet() as subnet:
+ with contextlib.nested(
+ self.pool(name="pool1"),
+ self.pool(name="pool2")
+ ) as (pool1, pool2):
+ with contextlib.nested(
+ self.vip(name='vip1', subnet=subnet, pool=pool1),
+ self.vip(name='vip2', subnet=subnet, pool=pool2)
+ ) as (vip1, vip2):
+ vip_data = {
+ 'id': vip2['vip']['id'],
+ 'name': 'vip1',
+ 'pool_id': pool1['pool']['id'],
+ }
+ self.assertRaises(loadbalancer.VipExists,
+ self.plugin.update_vip,
+ context.get_admin_context(),
+ vip2['vip']['id'],
+ {'vip': vip_data})
+
+ def test_update_vip_change_pool(self):
+ with self.subnet() as subnet:
+ with contextlib.nested(
+ self.pool(name="pool1"),
+ self.pool(name="pool2")
+ ) as (pool1, pool2):
+ with self.vip(name='vip1', subnet=subnet, pool=pool1) as vip:
+ # change vip from pool1 to pool2
+ vip_data = {
+ 'id': vip['vip']['id'],
+ 'name': 'vip1',
+ 'pool_id': pool2['pool']['id'],
+ }
+ ctx = context.get_admin_context()
+ self.plugin.update_vip(ctx,
+ vip['vip']['id'],
+ {'vip': vip_data})
+ db_pool2 = (ctx.session.query(ldb.Pool).
+ filter_by(id=pool2['pool']['id']).one())
+ db_pool1 = (ctx.session.query(ldb.Pool).
+ filter_by(id=pool1['pool']['id']).one())
+ # check that pool1.vip became None
+ self.assertIsNone(db_pool1.vip)
+ # and pool2 got vip
+ self.assertEqual(db_pool2.vip.id, vip['vip']['id'])
+
def test_create_vip_with_invalid_values(self):
invalid = {
'protocol': 'UNSUPPORTED',