Merge "Remove baylock"
This commit is contained in:
commit
2862a60203
|
@ -83,7 +83,6 @@ magnum/tests/unit/objects/test_objects.py::
|
|||
|
||||
object_data = {
|
||||
'Bay': '1.0-35edde13ad178e9419e7ea8b6d580bcd',
|
||||
'BayLock': '1.0-7d1eb08cf2070523bd210369c7a2e076',
|
||||
'BayModel': '1.0-06863f04ab4b98307e3d1b736d3137bf',
|
||||
'Container': '1.1-22b40e8eed0414561ca921906b189820',
|
||||
'MyObj': '1.0-b43567e512438205e32f4e95ca616697',
|
||||
|
|
|
@ -1,131 +0,0 @@
|
|||
#
|
||||
# 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 contextlib
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
import oslo_messaging as messaging
|
||||
from oslo_utils import excutils
|
||||
|
||||
from magnum.common import exception
|
||||
from magnum.conductor.api import ListenerAPI
|
||||
from magnum.i18n import _LI
|
||||
from magnum.i18n import _LW
|
||||
from magnum import objects
|
||||
|
||||
|
||||
cfg.CONF.import_opt('topic', 'magnum.conductor.config',
|
||||
group='conductor')
|
||||
cfg.CONF.import_opt('conductor_life_check_timeout', 'magnum.conductor.config',
|
||||
group='conductor')
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BayLock(object):
|
||||
|
||||
def __init__(self, context, bay, conductor_id):
|
||||
self.context = context
|
||||
self.bay = bay
|
||||
self.conductor_id = conductor_id
|
||||
|
||||
@staticmethod
|
||||
def conductor_alive(context, conductor_id):
|
||||
topic = cfg.CONF.conductor.topic
|
||||
timeout = cfg.CONF.conductor.conductor_life_check_timeout
|
||||
listener_api = ListenerAPI(context=context, topic=topic,
|
||||
server=conductor_id, timeout=timeout)
|
||||
try:
|
||||
return listener_api.ping_conductor()
|
||||
except messaging.MessagingTimeout:
|
||||
return False
|
||||
|
||||
def acquire(self, retry=True):
|
||||
"""Acquire a lock on the bay.
|
||||
|
||||
:param retry: When True, retry if lock was released while stealing.
|
||||
"""
|
||||
lock_conductor_id = objects.BayLock.create(self.bay.uuid,
|
||||
self.conductor_id)
|
||||
if lock_conductor_id is None:
|
||||
LOG.debug("Conductor %(conductor)s acquired lock on bay "
|
||||
"%(bay)s" % {'conductor': self.conductor_id,
|
||||
'bay': self.bay.uuid})
|
||||
return
|
||||
|
||||
if (lock_conductor_id == self.conductor_id or
|
||||
self.conductor_alive(self.context, lock_conductor_id)):
|
||||
LOG.debug("Lock on bay %(bay)s is owned by conductor "
|
||||
"%(conductor)s" % {'bay': self.bay.uuid,
|
||||
'conductor': lock_conductor_id})
|
||||
raise exception.OperationInProgress(bay_name=self.bay.name)
|
||||
else:
|
||||
LOG.info(_LI("Stale lock detected on bay %(bay)s. Conductor "
|
||||
"%(conductor)s will attempt to steal the lock"),
|
||||
{'bay': self.bay.uuid, 'conductor': self.conductor_id})
|
||||
|
||||
result = objects.BayLock.steal(self.bay.uuid,
|
||||
lock_conductor_id,
|
||||
self.conductor_id)
|
||||
|
||||
if result is None:
|
||||
LOG.info(_LI("Conductor %(conductor)s successfully stole the "
|
||||
"lock on bay %(bay)s"),
|
||||
{'conductor': self.conductor_id,
|
||||
'bay': self.bay.uuid})
|
||||
return
|
||||
elif result is True:
|
||||
if retry:
|
||||
LOG.info(_LI("The lock on bay %(bay)s was released while "
|
||||
"conductor %(conductor)s was stealing it. "
|
||||
"Trying again"),
|
||||
{'bay': self.bay.uuid,
|
||||
'conductor': self.conductor_id})
|
||||
return self.acquire(retry=False)
|
||||
else:
|
||||
new_lock_conductor_id = result
|
||||
LOG.info(_LI("Failed to steal lock on bay %(bay)s. "
|
||||
"Conductor %(conductor)s stole the lock first"),
|
||||
{'bay': self.bay.uuid,
|
||||
'conductor': new_lock_conductor_id})
|
||||
|
||||
raise exception.OperationInProgress(bay_name=self.bay.name)
|
||||
|
||||
def release(self, bay_uuid):
|
||||
"""Release a bay lock."""
|
||||
# Only the conductor that owns the lock will be releasing it.
|
||||
result = objects.BayLock.release(bay_uuid, self.conductor_id)
|
||||
if result is True:
|
||||
LOG.warn(_LW("Lock was already released on bay %s!"), bay_uuid)
|
||||
else:
|
||||
LOG.debug("Conductor %(conductor)s released lock on bay "
|
||||
"%(bay)s" % {'conductor': self.conductor_id,
|
||||
'bay': bay_uuid})
|
||||
|
||||
@contextlib.contextmanager
|
||||
def thread_lock(self, bay_uuid):
|
||||
"""Acquire a lock and release it only if there is an exception.
|
||||
|
||||
The release method still needs to be scheduled to be run at the
|
||||
end of the thread using the Thread.link method.
|
||||
"""
|
||||
try:
|
||||
self.acquire()
|
||||
yield
|
||||
except exception.OperationInProgress:
|
||||
raise
|
||||
except: # noqa
|
||||
with excutils.save_and_reraise_exception():
|
||||
self.release(bay_uuid)
|
|
@ -121,41 +121,6 @@ class Connection(object):
|
|||
:raises: BayNotFound
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def create_bay_lock(self, bay_uuid, conductor_id):
|
||||
"""Create a new baylock.
|
||||
|
||||
This method will fail if the bay has already been locked.
|
||||
|
||||
:param bay_uuid: The uuid of a bay.
|
||||
:param conductor_id: The id of a conductor.
|
||||
:returns: None if success.
|
||||
Otherwise, the id of the conductor that locks the bay.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def steal_bay_lock(self, bay_uuid, old_conductor_id, new_conductor_id):
|
||||
"""Steal lock of a bay.
|
||||
|
||||
Lock the bay with new_conductor_id if the bay is currently locked by
|
||||
old_conductor_id.
|
||||
|
||||
:param bay_uuid: The uuid of a bay.
|
||||
:param old_conductor_id: The id of the old conductor.
|
||||
:param new_conductor_id: The id of the new conductor.
|
||||
:returns: None if success. True if the bay is not locked.
|
||||
Otherwise, the id of the conductor that locks the bay.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def release_bay_lock(self, bay_uuid, conductor_id):
|
||||
"""Release lock of a bay.
|
||||
|
||||
:param bay_uuid: The uuid of a bay.
|
||||
:param conductor_id: The id of a conductor.
|
||||
:returns: None if success. True otherwise.
|
||||
"""
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_baymodel_list(self, context, filters=None,
|
||||
limit=None, marker=None, sort_key=None,
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
# 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.
|
||||
|
||||
"""remove baylock
|
||||
|
||||
Revision ID: 57fbdf2327a2
|
||||
Revises: adc3b7679ae
|
||||
Create Date: 2015-12-17 09:27:18.429773
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '57fbdf2327a2'
|
||||
down_revision = 'adc3b7679ae'
|
||||
|
||||
from alembic import op
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.drop_table('baylock')
|
|
@ -252,38 +252,6 @@ class Connection(api.Connection):
|
|||
ref.update(values)
|
||||
return ref
|
||||
|
||||
def create_bay_lock(self, bay_uuid, conductor_id):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
query = model_query(models.BayLock, session=session)
|
||||
lock = query.filter_by(bay_uuid=bay_uuid).first()
|
||||
if lock is not None:
|
||||
return lock.conductor_id
|
||||
session.add(models.BayLock(bay_uuid=bay_uuid,
|
||||
conductor_id=conductor_id))
|
||||
|
||||
def steal_bay_lock(self, bay_uuid, old_conductor_id, new_conductor_id):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
query = model_query(models.BayLock, session=session)
|
||||
lock = query.filter_by(bay_uuid=bay_uuid).first()
|
||||
if lock is None:
|
||||
return True
|
||||
elif lock.conductor_id != old_conductor_id:
|
||||
return lock.conductor_id
|
||||
else:
|
||||
lock.update({'conductor_id': new_conductor_id})
|
||||
|
||||
def release_bay_lock(self, bay_uuid, conductor_id):
|
||||
session = get_session()
|
||||
with session.begin():
|
||||
query = model_query(models.BayLock, session=session)
|
||||
query = query.filter_by(bay_uuid=bay_uuid,
|
||||
conductor_id=conductor_id)
|
||||
count = query.delete()
|
||||
if count == 0:
|
||||
return True
|
||||
|
||||
def _add_baymodels_filters(self, query, filters):
|
||||
if filters is None:
|
||||
filters = {}
|
||||
|
|
|
@ -132,19 +132,6 @@ class Bay(Base):
|
|||
magnum_cert_ref = Column(String(512))
|
||||
|
||||
|
||||
class BayLock(Base):
|
||||
"""Represents a baylock."""
|
||||
|
||||
__tablename__ = 'baylock'
|
||||
__table_args__ = (
|
||||
schema.UniqueConstraint('bay_uuid', name='uniq_baylock0bay_uuid'),
|
||||
table_args()
|
||||
)
|
||||
id = Column(Integer, primary_key=True)
|
||||
bay_uuid = Column(String(36))
|
||||
conductor_id = Column(String(64))
|
||||
|
||||
|
||||
class BayModel(Base):
|
||||
"""Represents a bay model."""
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
# under the License.
|
||||
|
||||
from magnum.objects import bay
|
||||
from magnum.objects import baylock
|
||||
from magnum.objects import baymodel
|
||||
from magnum.objects import certificate
|
||||
from magnum.objects import container
|
||||
|
@ -27,7 +26,6 @@ from magnum.objects import x509keypair
|
|||
|
||||
Container = container.Container
|
||||
Bay = bay.Bay
|
||||
BayLock = baylock.BayLock
|
||||
BayModel = baymodel.BayModel
|
||||
MagnumService = magnum_service.MagnumService
|
||||
Node = node.Node
|
||||
|
@ -37,7 +35,6 @@ Service = service.Service
|
|||
X509KeyPair = x509keypair.X509KeyPair
|
||||
Certificate = certificate.Certificate
|
||||
__all__ = (Bay,
|
||||
BayLock,
|
||||
BayModel,
|
||||
Container,
|
||||
MagnumService,
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
# 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 oslo_versionedobjects import fields
|
||||
|
||||
from magnum.db import api as dbapi
|
||||
from magnum.objects import base
|
||||
|
||||
|
||||
@base.MagnumObjectRegistry.register
|
||||
class BayLock(base.MagnumPersistentObject, base.MagnumObject,
|
||||
base.MagnumObjectDictCompat):
|
||||
# Version 1.0: Initial version
|
||||
VERSION = '1.0'
|
||||
|
||||
dbapi = dbapi.get_instance()
|
||||
|
||||
fields = {
|
||||
'id': fields.IntegerField(),
|
||||
'bay_uuid': fields.StringField(nullable=True),
|
||||
'conductor_id': fields.StringField(nullable=True),
|
||||
}
|
||||
|
||||
@base.remotable_classmethod
|
||||
def create(cls, bay_uuid, conductor_id):
|
||||
return cls.dbapi.create_bay_lock(bay_uuid, conductor_id)
|
||||
|
||||
@base.remotable_classmethod
|
||||
def steal(cls, bay_uuid, old_conductor_id, new_conductor_id):
|
||||
return cls.dbapi.steal_bay_lock(bay_uuid, old_conductor_id,
|
||||
new_conductor_id)
|
||||
|
||||
@base.remotable_classmethod
|
||||
def release(cls, bay_uuid, conductor_id):
|
||||
return cls.dbapi.release_bay_lock(bay_uuid, conductor_id)
|
|
@ -1,185 +0,0 @@
|
|||
#
|
||||
# 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 mock
|
||||
import oslo_messaging as messaging
|
||||
|
||||
from magnum.common import exception
|
||||
from magnum.common import short_id
|
||||
from magnum.conductor import bay_lock
|
||||
from magnum.tests import base
|
||||
from magnum.tests.unit.objects import utils as obj_utils
|
||||
from mock import patch
|
||||
|
||||
|
||||
class BayLockTest(base.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(BayLockTest, self).setUp()
|
||||
self.conductor_id = short_id.generate_id()
|
||||
self.bay = obj_utils.get_test_bay(self.context)
|
||||
|
||||
class TestThreadLockException(Exception):
|
||||
pass
|
||||
|
||||
@patch('magnum.objects.BayLock.create', return_value=None)
|
||||
def test_successful_acquire_new_lock(self, mock_object_create):
|
||||
baylock = bay_lock.BayLock(self.context, self.bay, self.conductor_id)
|
||||
baylock.acquire()
|
||||
|
||||
mock_object_create.assert_called_once_with(self.bay.uuid,
|
||||
self.conductor_id)
|
||||
|
||||
@patch('magnum.objects.BayLock.create')
|
||||
def test_failed_acquire_current_conductor_lock(self, mock_object_create):
|
||||
mock_object_create.return_value = self.conductor_id
|
||||
|
||||
baylock = bay_lock.BayLock(self.context, self.bay, self.conductor_id)
|
||||
|
||||
self.assertRaises(exception.OperationInProgress, baylock.acquire)
|
||||
mock_object_create.assert_called_once_with(self.bay.uuid,
|
||||
self.conductor_id)
|
||||
|
||||
@patch('magnum.objects.BayLock.steal', return_value=None)
|
||||
@patch('magnum.objects.BayLock.create', return_value='fake-conductor-id')
|
||||
def test_successful_acquire_dead_conductor_lock(self, mock_object_create,
|
||||
mock_object_steal):
|
||||
baylock = bay_lock.BayLock(self.context, self.bay, self.conductor_id)
|
||||
with mock.patch.object(baylock, 'conductor_alive',
|
||||
return_value=False):
|
||||
baylock.acquire()
|
||||
|
||||
mock_object_create.assert_called_once_with(self.bay.uuid,
|
||||
self.conductor_id)
|
||||
mock_object_steal.assert_called_once_with(
|
||||
self.bay.uuid,
|
||||
'fake-conductor-id', self.conductor_id)
|
||||
|
||||
@patch('magnum.objects.BayLock.create', return_value='fake-conductor-id')
|
||||
def test_failed_acquire_alive_conductor_lock(self, mock_object_create):
|
||||
baylock = bay_lock.BayLock(self.context, self.bay, self.conductor_id)
|
||||
with mock.patch.object(baylock, 'conductor_alive',
|
||||
return_value=True):
|
||||
self.assertRaises(exception.OperationInProgress, baylock.acquire)
|
||||
|
||||
mock_object_create.assert_called_once_with(self.bay.uuid,
|
||||
self.conductor_id)
|
||||
|
||||
@patch('magnum.objects.BayLock.steal', return_value='fake-conductor-id2')
|
||||
@patch('magnum.objects.BayLock.create', return_value='fake-conductor-id')
|
||||
def test_failed_acquire_dead_conductor_lock(self, mock_object_create,
|
||||
mock_object_steal):
|
||||
baylock = bay_lock.BayLock(self.context, self.bay, self.conductor_id)
|
||||
with mock.patch.object(baylock, 'conductor_alive',
|
||||
return_value=False):
|
||||
self.assertRaises(exception.OperationInProgress, baylock.acquire)
|
||||
|
||||
mock_object_create.assert_called_once_with(self.bay.uuid,
|
||||
self.conductor_id)
|
||||
mock_object_steal.assert_called_once_with(
|
||||
self.bay.uuid,
|
||||
'fake-conductor-id', self.conductor_id)
|
||||
|
||||
@patch('magnum.objects.BayLock.steal', side_effect=[True, None])
|
||||
@patch('magnum.objects.BayLock.create', return_value='fake-conductor-id')
|
||||
def test_successful_acquire_with_retry(self, mock_object_create,
|
||||
mock_object_steal):
|
||||
baylock = bay_lock.BayLock(self.context, self.bay, self.conductor_id)
|
||||
with mock.patch.object(baylock, 'conductor_alive',
|
||||
return_value=False):
|
||||
baylock.acquire()
|
||||
|
||||
mock_object_create.assert_has_calls(
|
||||
[mock.call(self.bay.uuid, self.conductor_id)] * 2)
|
||||
mock_object_steal.assert_has_calls(
|
||||
[mock.call(self.bay.uuid, 'fake-conductor-id',
|
||||
self.conductor_id)] * 2)
|
||||
|
||||
@patch('magnum.objects.BayLock.steal', return_value=True)
|
||||
@patch('magnum.objects.BayLock.create', return_value='fake-conductor-id')
|
||||
def test_failed_acquire_one_retry_only(self, mock_object_create,
|
||||
mock_object_steal):
|
||||
baylock = bay_lock.BayLock(self.context, self.bay, self.conductor_id)
|
||||
with mock.patch.object(baylock, 'conductor_alive',
|
||||
return_value=False):
|
||||
self.assertRaises(exception.OperationInProgress, baylock.acquire)
|
||||
|
||||
mock_object_create.assert_has_calls(
|
||||
[mock.call(self.bay.uuid, self.conductor_id)] * 2)
|
||||
mock_object_steal.assert_has_calls(
|
||||
[mock.call(self.bay.uuid, 'fake-conductor-id',
|
||||
self.conductor_id)] * 2)
|
||||
|
||||
@patch('magnum.objects.BayLock.release', return_value=None)
|
||||
@patch('magnum.objects.BayLock.create', return_value=None)
|
||||
def test_thread_lock_acquire_success_with_exception(self,
|
||||
mock_object_create,
|
||||
mock_object_release):
|
||||
baylock = bay_lock.BayLock(self.context, self.bay, self.conductor_id)
|
||||
|
||||
def check_thread_lock():
|
||||
with baylock.thread_lock(self.bay.uuid):
|
||||
self.assertEqual(1, mock_object_create.call_count)
|
||||
raise self.TestThreadLockException
|
||||
|
||||
self.assertRaises(self.TestThreadLockException, check_thread_lock)
|
||||
self.assertEqual(1, mock_object_release.call_count)
|
||||
|
||||
@patch('magnum.objects.BayLock.release', return_value=None)
|
||||
@patch('magnum.objects.BayLock.create')
|
||||
def test_thread_lock_acquire_fail_with_exception(self, mock_object_create,
|
||||
mock_object_release):
|
||||
mock_object_create.return_value = self.conductor_id
|
||||
baylock = bay_lock.BayLock(self.context, self.bay, self.conductor_id)
|
||||
|
||||
def check_thread_lock():
|
||||
with baylock.thread_lock(self.bay.uuid):
|
||||
self.assertEqual(1, mock_object_create.call_count)
|
||||
raise exception.OperationInProgress
|
||||
|
||||
self.assertRaises(exception.OperationInProgress, check_thread_lock)
|
||||
assert not mock_object_release.called
|
||||
|
||||
@patch('magnum.objects.BayLock.release', return_value=None)
|
||||
@patch('magnum.objects.BayLock.create', return_value=None)
|
||||
def test_thread_lock_acquire_success_no_exception(self, mock_object_create,
|
||||
mock_object_release):
|
||||
baylock = bay_lock.BayLock(self.context, self.bay, self.conductor_id)
|
||||
with baylock.thread_lock(self.bay.uuid):
|
||||
self.assertEqual(1, mock_object_create.call_count)
|
||||
assert not mock_object_release.called
|
||||
|
||||
@patch('magnum.conductor.api.ListenerAPI.__new__')
|
||||
def test_conductor_alive_ok(self, mock_listener_api_new):
|
||||
mock_listener_api = mock.MagicMock()
|
||||
mock_listener_api.ping_conductor.return_value = True
|
||||
mock_listener_api_new.return_value = mock_listener_api
|
||||
baylock = bay_lock.BayLock(self.context, self.bay, self.conductor_id)
|
||||
|
||||
ret = baylock.conductor_alive(self.context, self.conductor_id)
|
||||
|
||||
self.assertIs(True, ret)
|
||||
self.assertEqual(1, mock_listener_api_new.call_count)
|
||||
|
||||
@patch('magnum.conductor.api.ListenerAPI.__new__')
|
||||
def test_conductor_alive_timeout(self, mock_listener_api_new):
|
||||
mock_listener_api = mock.MagicMock()
|
||||
mock_listener_api.ping_conductor.side_effect = (
|
||||
messaging.MessagingTimeout('too slow'))
|
||||
mock_listener_api_new.return_value = mock_listener_api
|
||||
baylock = bay_lock.BayLock(self.context, self.bay, self.conductor_id)
|
||||
|
||||
ret = baylock.conductor_alive(self.context, self.conductor_id)
|
||||
|
||||
self.assertIs(False, ret)
|
||||
self.assertEqual(1, mock_listener_api_new.call_count)
|
|
@ -1,88 +0,0 @@
|
|||
# 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.
|
||||
|
||||
"""Tests for manipulating BayLocks via the DB API"""
|
||||
|
||||
import uuid
|
||||
|
||||
from magnum.tests.unit.db import base
|
||||
from magnum.tests.unit.db import utils as utils
|
||||
|
||||
|
||||
class DbBayLockTestCase(base.DbTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(DbBayLockTestCase, self).setUp()
|
||||
self.bay = utils.create_test_bay()
|
||||
|
||||
def test_create_bay_lock_success(self):
|
||||
ret = self.dbapi.create_bay_lock(self.bay.uuid, str(uuid.uuid4()))
|
||||
self.assertIsNone(ret)
|
||||
|
||||
def test_create_bay_lock_fail_double_same(self):
|
||||
conductor_id = str(uuid.uuid4())
|
||||
self.dbapi.create_bay_lock(self.bay.uuid, conductor_id)
|
||||
ret = self.dbapi.create_bay_lock(self.bay.uuid, conductor_id)
|
||||
self.assertEqual(conductor_id, ret)
|
||||
|
||||
def test_create_bay_lock_fail_double_different(self):
|
||||
conductor_id = str(uuid.uuid4())
|
||||
self.dbapi.create_bay_lock(self.bay.uuid, conductor_id)
|
||||
ret = self.dbapi.create_bay_lock(self.bay.uuid, str(uuid.uuid4()))
|
||||
self.assertEqual(conductor_id, ret)
|
||||
|
||||
def test_steal_bay_lock_success(self):
|
||||
conductor_id = str(uuid.uuid4())
|
||||
self.dbapi.create_bay_lock(self.bay.uuid, conductor_id)
|
||||
ret = self.dbapi.steal_bay_lock(self.bay.uuid, conductor_id,
|
||||
str(uuid.uuid4()))
|
||||
self.assertIsNone(ret)
|
||||
|
||||
def test_steal_bay_lock_fail_gone(self):
|
||||
conductor_id = str(uuid.uuid4())
|
||||
self.dbapi.create_bay_lock(self.bay.uuid, conductor_id)
|
||||
self.dbapi.release_bay_lock(self.bay.uuid, conductor_id)
|
||||
ret = self.dbapi.steal_bay_lock(self.bay.uuid, conductor_id,
|
||||
str(uuid.uuid4()))
|
||||
self.assertTrue(ret)
|
||||
|
||||
def test_steal_bay_lock_fail_stolen(self):
|
||||
conductor_id = str(uuid.uuid4())
|
||||
self.dbapi.create_bay_lock(self.bay.uuid, conductor_id)
|
||||
|
||||
# Simulate stolen lock
|
||||
conductor_id2 = str(uuid.uuid4())
|
||||
self.dbapi.release_bay_lock(self.bay.uuid, conductor_id)
|
||||
self.dbapi.create_bay_lock(self.bay.uuid, conductor_id2)
|
||||
|
||||
ret = self.dbapi.steal_bay_lock(self.bay.uuid, str(uuid.uuid4()),
|
||||
conductor_id2)
|
||||
self.assertEqual(conductor_id2, ret)
|
||||
|
||||
def test_release_bay_lock_success(self):
|
||||
conductor_id = str(uuid.uuid4())
|
||||
self.dbapi.create_bay_lock(self.bay.uuid, conductor_id)
|
||||
ret = self.dbapi.release_bay_lock(self.bay.uuid, conductor_id)
|
||||
self.assertIsNone(ret)
|
||||
|
||||
def test_release_bay_lock_fail_double(self):
|
||||
conductor_id = str(uuid.uuid4())
|
||||
self.dbapi.create_bay_lock(self.bay.uuid, conductor_id)
|
||||
self.dbapi.release_bay_lock(self.bay.uuid, conductor_id)
|
||||
ret = self.dbapi.release_bay_lock(self.bay.uuid, conductor_id)
|
||||
self.assertTrue(ret)
|
||||
|
||||
def test_release_bay_lock_fail_wrong_conductor_id(self):
|
||||
conductor_id = str(uuid.uuid4())
|
||||
self.dbapi.create_bay_lock(self.bay.uuid, conductor_id)
|
||||
ret = self.dbapi.release_bay_lock(self.bay.uuid, str(uuid.uuid4()))
|
||||
self.assertTrue(ret)
|
|
@ -278,15 +278,6 @@ def create_test_rc(**kw):
|
|||
return dbapi.create_rc(replication_controller)
|
||||
|
||||
|
||||
def get_test_baylock(**kw):
|
||||
return {
|
||||
'id': kw.get('id', 42),
|
||||
'bay_uuid': kw.get('bay_uuid', '5d12f6fd-a196-4bf0-ae4c-1f639a523a52'),
|
||||
'conductor_id': kw.get('conductor_id',
|
||||
'72625085-c507-4410-9b28-cd7cf1fbf1ad'),
|
||||
}
|
||||
|
||||
|
||||
def get_test_x509keypair(**kw):
|
||||
return {
|
||||
'id': kw.get('id', 42),
|
||||
|
|
|
@ -1,52 +0,0 @@
|
|||
# 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 mock
|
||||
import uuid
|
||||
|
||||
from magnum import objects
|
||||
from magnum.tests.unit.db import base
|
||||
from magnum.tests.unit.db import utils
|
||||
|
||||
|
||||
class TestBayLockObject(base.DbTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestBayLockObject, self).setUp()
|
||||
baylock_dict = utils.get_test_baylock()
|
||||
self.bay_uuid = baylock_dict['bay_uuid']
|
||||
self.conductor_id = baylock_dict['conductor_id']
|
||||
|
||||
def test_create(self):
|
||||
with mock.patch.object(self.dbapi, 'create_bay_lock',
|
||||
autospec=True) as mock_create_baylock:
|
||||
objects.BayLock.create(self.bay_uuid, self.conductor_id)
|
||||
mock_create_baylock.assert_called_once_with(self.bay_uuid,
|
||||
self.conductor_id)
|
||||
|
||||
def test_steal(self):
|
||||
with mock.patch.object(self.dbapi, 'steal_bay_lock',
|
||||
autospec=True) as mock_steal_baylock:
|
||||
old_conductor_id = self.conductor_id
|
||||
new_conductor_id = str(uuid.uuid4())
|
||||
objects.BayLock.steal(self.bay_uuid, old_conductor_id,
|
||||
new_conductor_id)
|
||||
mock_steal_baylock.assert_called_once_with(
|
||||
self.bay_uuid,
|
||||
old_conductor_id, new_conductor_id)
|
||||
|
||||
def test_release(self):
|
||||
with mock.patch.object(self.dbapi, 'release_bay_lock',
|
||||
autospec=True) as mock_release_baylock:
|
||||
objects.BayLock.release(self.bay_uuid, self.conductor_id)
|
||||
mock_release_baylock.assert_called_once_with(self.bay_uuid,
|
||||
self.conductor_id)
|
|
@ -424,7 +424,6 @@ class _TestObject(object):
|
|||
# http://docs.openstack.org/developer/magnum/objects.html
|
||||
object_data = {
|
||||
'Bay': '1.2-0749bac339a2cc24dc03f45a4359013d',
|
||||
'BayLock': '1.0-7d1eb08cf2070523bd210369c7a2e076',
|
||||
'BayModel': '1.8-a4bb0976be245f06edbd1db087a18071',
|
||||
'Certificate': '1.0-2aff667971b85c1edf8d15684fd7d5e2',
|
||||
'Container': '1.3-e2d9d2e8a8844d421148cd9fde6c6bd6',
|
||||
|
|
Loading…
Reference in New Issue