At most there should only be 1 entry in this DB table.

Enforce this by using the same value for the primary key column.

Change-Id: Iedbd2e9b90200f703d05dc3932bfbace398e81e9
This commit is contained in:
Kent Wu 2019-04-04 11:51:26 -07:00
parent 87b14aee36
commit f617775213
4 changed files with 28 additions and 8 deletions

View File

@ -35,8 +35,9 @@ def upgrade():
)
op.create_table(
'apic_aim_vm_name_updates',
sa.Column('purpose', sa.String(36), nullable=False),
sa.PrimaryKeyConstraint('purpose'),
sa.Column('host_id', sa.String(36), nullable=False),
sa.PrimaryKeyConstraint('host_id'),
sa.Column('last_incremental_update_time', sa.DateTime()),
sa.Column('last_full_update_time', sa.DateTime()),
)

View File

@ -25,6 +25,7 @@ import sqlalchemy as sa
from sqlalchemy.ext import baked
from sqlalchemy import orm
VM_UPDATE_PURPOSE = 'VmUpdate'
LOG = log.getLogger(__name__)
@ -109,12 +110,14 @@ class VMName(model_base.BASEV2):
# At any point of time, there should only be one entry in this table.
# That entry is used to make sure only one controller is actively updating
# the VMName table.
# We will enforce that by using the same value for the purpose column which
# is the primary key. That entry is used to make sure only one controller is
# actively updating the VMName table.
class VMNameUpdate(model_base.BASEV2):
__tablename__ = 'apic_aim_vm_name_updates'
host_id = sa.Column(sa.String(36), primary_key=True)
purpose = sa.Column(sa.String(36), primary_key=True)
host_id = sa.Column(sa.String(36))
last_incremental_update_time = sa.Column(sa.DateTime)
last_full_update_time = sa.Column(sa.DateTime)
@ -522,7 +525,8 @@ class DbMixin(object):
if last_full_update_time:
db_obj.last_full_update_time = last_full_update_time
else:
db_obj = VMNameUpdate(host_id=host_id,
db_obj = VMNameUpdate(
purpose=VM_UPDATE_PURPOSE, host_id=host_id,
last_incremental_update_time=last_incremental_update_time,
last_full_update_time=last_full_update_time)
session.add(db_obj)

View File

@ -292,9 +292,16 @@ class ApicMechanismDriver(api_plus.MechanismDriver,
if nova_vms is None:
return
self._set_vm_name_update(session, vm_name_update, self.host_id,
current_time,
current_time if is_full_update else None)
try:
self._set_vm_name_update(session, vm_name_update, self.host_id,
current_time,
current_time if is_full_update else None)
# This means another controller is also adding an entry at the same
# time and he has beat us. This is fine so we will just return.
except Exception as e:
LOG.warning(e)
return
vm_list = []
for vm in nova_vms:
vm_list.append((vm.id, vm.name))

View File

@ -19,6 +19,7 @@ import fixtures
import mock
import netaddr
import six
from sqlalchemy.orm import exc as sql_exc
import testtools
from aim.aim_lib import nat_strategy
@ -1952,6 +1953,13 @@ class TestAimMapping(ApicAimTestCase):
self.assertEqual(self.driver._get_vm_names(self.db_session),
[])
# This should throw an exception as there will be only one
# entry in this DB table at any given time.
current_time = datetime.datetime.now()
self.assertRaises(sql_exc.FlushError,
self.driver._set_vm_name_update,
self.db_session, None, 'host_id1', current_time)
def test_multi_scope_routing_with_unscoped_pools(self):
self._test_multi_scope_routing(True)