implement locking mechanism in rally
Rally is not having locking mechanism to control rally processes simultaneous access to the same OSP resource. For example, we don't want two different rally processes to delete the same floating ip. In this implementation we create a "RallyLock" table in rally DB which can store a unique UUID. When a user wants only one process to modify a OSP resource at a time, take a lock by inserting resource's (for example floating ip) uuid into this table. If another process wants to take lock, it will get error as table won't allow duplicate values for uuid. Sqlalchemy is throwing errors when this DB code is implemented as a rally plugin. So we needed to find the alternate option i.e python package to make this DB changes working. To acquire and release a lock, rally scenario has to call the api like from browbeat_rally.db import api as db_api from oslo_db import exception as db_exc net_id = net['network']['id'] try: db_api.acquire_lock(net_id) except db_exc.DBDuplicateEntry: LOG.info("This uuid {} is already in use".format(net_id)) db_api.release_lock(net_id) Change-Id: I0c14a3c0ddb3e2d4e3478e763d2ee4066440b9ac
This commit is contained in:
parent
06f1a7c6c7
commit
cf541956e8
@ -0,0 +1,32 @@
|
||||
# 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.
|
||||
from rally.common import db
|
||||
|
||||
from browbeat_rally.db import models
|
||||
|
||||
|
||||
@db.with_session
|
||||
def get_lock(session, lock_uuid):
|
||||
lock = models.RallyLock(lock_uuid=lock_uuid)
|
||||
session.add(lock)
|
||||
session.commit()
|
||||
lock = lock.as_dict()
|
||||
return lock
|
||||
|
||||
|
||||
@db.with_session
|
||||
def lock_list(session):
|
||||
locks = []
|
||||
query = session.query(models.RallyLock)
|
||||
for lock in query.all():
|
||||
locks.append(lock.as_dict())
|
||||
return locks
|
@ -0,0 +1,23 @@
|
||||
# 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.
|
||||
import sqlalchemy as sa
|
||||
|
||||
from rally.common.db import models
|
||||
|
||||
|
||||
BASE = models.BASE
|
||||
|
||||
|
||||
class RallyLock(BASE, models.RallyBase):
|
||||
__tablename__ = "rallylocks"
|
||||
|
||||
lock_uuid = sa.Column(sa.String(36), primary_key=True, nullable=False)
|
@ -0,0 +1,46 @@
|
||||
# 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.
|
||||
import tempfile
|
||||
from sqlalchemy import schema
|
||||
from oslo_db import options as db_options
|
||||
from browbeat_rally.db import models
|
||||
from rally.common import cfg
|
||||
from oslo_db.sqlalchemy import session as db_session
|
||||
|
||||
|
||||
CONF = cfg.CONF
|
||||
|
||||
# rally.conf always uses stack.sqlite database
|
||||
db_options.set_defaults(
|
||||
CONF, connection="sqlite:///%s/stack.sqlite" % tempfile.gettempdir())
|
||||
|
||||
|
||||
def _create_facade_lazily():
|
||||
return db_session.EngineFacade.from_config(CONF)
|
||||
|
||||
|
||||
def get_engine():
|
||||
facade = _create_facade_lazily()
|
||||
return facade.get_engine()
|
||||
|
||||
|
||||
# alternate way to create engine is
|
||||
# from oslo_db.sqlalchemy import engines
|
||||
# engine = engines.create_engine("sqlite:///%s/stack.sqlite" % tempfile.gettempdir())
|
||||
def schema_create():
|
||||
engine = get_engine()
|
||||
metadata = schema.MetaData()
|
||||
table = schema.Table("rallylocks", metadata)
|
||||
# delete rallylocks table
|
||||
models.BASE.metadata.drop_all(engine, [table], checkfirst=True)
|
||||
# recreate rallylocks table
|
||||
models.BASE.metadata.create_all(engine)
|
18
ansible/install/roles/rally/files/browbeat-rally/setup.py
Normal file
18
ansible/install/roles/rally/files/browbeat-rally/setup.py
Normal file
@ -0,0 +1,18 @@
|
||||
# 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.
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
setup(
|
||||
name='browbeat_rally',
|
||||
version='0.0.1',
|
||||
packages=find_packages(),)
|
16
ansible/install/roles/rally/files/create_lock_table.py
Normal file
16
ansible/install/roles/rally/files/create_lock_table.py
Normal file
@ -0,0 +1,16 @@
|
||||
# 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.
|
||||
from browbeat_rally.db import schema
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
schema.schema_create()
|
@ -56,6 +56,25 @@
|
||||
- name: Setup rally database
|
||||
shell: . {{ rally_venv }}/bin/activate; rally db recreate
|
||||
|
||||
# Install rally extra code which we develop in browbeat
|
||||
# as python package. This code can be used in browbeat rally plugins.
|
||||
# Sqlalchemy giving errors when we run this extra DB code as rally plugin
|
||||
# so we came up with this python package approach.
|
||||
- name: install rally browbeat code
|
||||
shell: |
|
||||
source {{ rally_venv }}/bin/activate
|
||||
pip install .
|
||||
args:
|
||||
executable: /bin/bash
|
||||
chdir: "{{ role_path }}/files/browbeat-rally"
|
||||
when: rhosp_version is version('15.0', '>=')
|
||||
|
||||
- name: create lock table in rally db for dynamic workloads
|
||||
shell: |
|
||||
source {{ rally_venv }}/bin/activate
|
||||
python {{ role_path }}/files/create_lock_table.py
|
||||
when: rhosp_version is version('15.0', '>=')
|
||||
|
||||
- block:
|
||||
- name: copy of stackrc
|
||||
copy:
|
||||
|
Loading…
x
Reference in New Issue
Block a user