Merge "Disallow duplicated policy name in DB"

This commit is contained in:
Jenkins 2016-09-30 00:37:53 +00:00 committed by Gerrit Code Review
commit aa869f3fa9
3 changed files with 39 additions and 7 deletions

View File

@ -102,9 +102,7 @@ class PolicyModel(base.APIModel):
'kind': item.get('kind'),
'desc': item.get('description')})
except exception.CongressException as e:
(num, desc) = error_codes.get('failed_to_create_policy')
raise webservice.DataModelException(
num, desc + ": " + str(e))
raise webservice.DataModelException.create(e)
return (policy_metadata['id'], policy_metadata)

View File

@ -18,6 +18,7 @@ from __future__ import division
from __future__ import absolute_import
from oslo_config import cfg
import sqlalchemy as sa
from sqlalchemy.orm import exc as db_exc
@ -59,10 +60,40 @@ class Policy(model_base.BASE, model_base.HasId, model_base.HasAudit):
def add_policy(id_, name, abbreviation, description, owner, kind,
deleted=False, session=None):
session = session or db.get_session()
with session.begin(subtransactions=True):
policy = Policy(id_, name, abbreviation, description, owner,
kind, deleted)
session.add(policy)
mysql = (cfg.CONF.database.connection is not None and
(cfg.CONF.database.connection.split(':/')[0] == 'mysql' or
cfg.CONF.database.connection.split('+')[0] == 'mysql'))
postgres = (cfg.CONF.database.connection is not None and
(cfg.CONF.database.connection.split(':/')[0] == 'postgresql' or
cfg.CONF.database.connection.split('+')[0] == 'postgresql'))
try:
with session.begin(subtransactions=True):
# lock policies table to prevent duplicate named policy being added
# after duplicate check but before transaction closes.
# supported DBs are SQLite and MySQL and Postgres
# TODO(ekcs): table locking is special to underlying DB
# change DB schema to prevent duplicate generically without locking
if mysql: # Explicitly LOCK TABLES for MySQL
session.execute('LOCK TABLES policies WRITE')
if postgres: # Explicitly LOCK TABLE for Postgres
session.execute('LOCK TABLE policies IN EXCLUSIVE MODE')
# Do nothing for SQLite; DB auto locked for transaction
# add if no policy of duplicate name exists
unique = (session.query(Policy).
filter(Policy.name == name).
filter(Policy.deleted == is_soft_deleted(name, deleted)).
count() == 0)
if unique:
policy = Policy(id_, name, abbreviation, description, owner,
kind, deleted)
session.add(policy)
finally: # always release table lock
if mysql:
session.execute('UNLOCK TABLES')
# postgres automatically releases lock after transaction completes
if not unique:
raise KeyError("Policy with name %s already exists" % name)
return policy

View File

@ -376,6 +376,9 @@ class Runtime (object):
obj['description'],
obj['owner_id'],
obj['kind'])
except KeyError:
raise exception.Conflict(
"Policy with name %s already exists" % name)
except Exception:
policy_name = policy_obj.name
msg = "Error thrown while adding policy %s into DB." % policy_name