Mox removal for instances_resize API tests

This is the last file using mox3 for testing, so mox3 is also removed
from test-requirements.txt.

Change-Id: Ie70adc620df04bf4e0ca43ff4e3060b449d2e377
Signed-off-by: Zhao Chao <zhaochao1984@gmail.com>
This commit is contained in:
Zhao Chao 2018-03-22 17:36:18 +08:00
parent b9a119eb02
commit b24828256c
2 changed files with 270 additions and 140 deletions

View File

@ -17,7 +17,6 @@ wsgi-intercept>=1.4.1 # MIT License
proboscis>=1.2.5.3 # Apache-2.0 proboscis>=1.2.5.3 # Apache-2.0
python-troveclient>=2.2.0 # Apache-2.0 python-troveclient>=2.2.0 # Apache-2.0
mock>=2.0.0 # BSD mock>=2.0.0 # BSD
mox3>=0.20.0 # Apache-2.0
testtools>=2.2.0 # MIT testtools>=2.2.0 # MIT
testrepository>=0.0.18 # Apache-2.0/BSD testrepository>=0.0.18 # Apache-2.0/BSD
pymongo!=3.1,>=3.0.2 # Apache-2.0 pymongo!=3.1,>=3.0.2 # Apache-2.0

View File

@ -13,8 +13,7 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
from mock import Mock import mock
from mox3 import mox
from novaclient.exceptions import BadRequest from novaclient.exceptions import BadRequest
from novaclient.v2.servers import Server from novaclient.v2.servers import Server
from oslo_messaging._drivers.common import RPCException from oslo_messaging._drivers.common import RPCException
@ -22,6 +21,7 @@ from proboscis import test
from testtools import TestCase from testtools import TestCase
from trove.common.exception import PollTimeOut from trove.common.exception import PollTimeOut
from trove.common.exception import TroveError
from trove.common import instance as rd_instance from trove.common import instance as rd_instance
from trove.common import template from trove.common import template
from trove.common import utils from trove.common import utils
@ -46,7 +46,6 @@ NEW_FLAVOR = nova.FLAVORS.get(NEW_FLAVOR_ID)
class ResizeTestBase(TestCase): class ResizeTestBase(TestCase):
def _init(self): def _init(self):
self.mock = mox.Mox()
self.instance_id = 500 self.instance_id = 500
context = trove_testtools.TroveTestContext(self) context = trove_testtools.TroveTestContext(self)
self.db_info = DBInstance.create( self.db_info = DBInstance.create(
@ -56,7 +55,7 @@ class ResizeTestBase(TestCase):
volume_size=None, volume_size=None,
datastore_version_id=test_config.dbaas_datastore_version_id, datastore_version_id=test_config.dbaas_datastore_version_id,
task_status=InstanceTasks.RESIZING) task_status=InstanceTasks.RESIZING)
self.server = self.mock.CreateMock(Server) self.server = mock.MagicMock(spec=Server)
self.instance = models.BuiltInstanceTasks( self.instance = models.BuiltInstanceTasks(
context, context,
self.db_info, self.db_info,
@ -65,47 +64,34 @@ class ResizeTestBase(TestCase):
instance_id=self.db_info.id, instance_id=self.db_info.id,
status=rd_instance.ServiceStatuses.RUNNING)) status=rd_instance.ServiceStatuses.RUNNING))
self.instance.server.flavor = {'id': OLD_FLAVOR_ID} self.instance.server.flavor = {'id': OLD_FLAVOR_ID}
self.guest = self.mock.CreateMock(guest.API) self.guest = mock.MagicMock(spec=guest.API)
self.instance._guest = self.guest self.instance._guest = self.guest
self.instance.refresh_compute_server_info = lambda: None self.instance.refresh_compute_server_info = lambda: None
self.instance._refresh_datastore_status = lambda: None self.instance._refresh_datastore_status = lambda: None
self.mock.StubOutWithMock(self.instance, 'update_db') self.instance.update_db = mock.Mock()
self.mock.StubOutWithMock(self.instance, self.instance.set_datastore_status_to_paused = mock.Mock()
'set_datastore_status_to_paused') self.poll_until_side_effects = []
self.poll_until_mocked = False
self.action = None self.action = None
def tearDown(self): def tearDown(self):
super(ResizeTestBase, self).tearDown() super(ResizeTestBase, self).tearDown()
self.mock.UnsetStubs()
self.db_info.delete() self.db_info.delete()
def _execute_action(self): def _poll_until(self, *args, **kwargs):
self.instance.update_db(task_status=InstanceTasks.NONE) try:
self.mock.ReplayAll() effect = self.poll_until_side_effects.pop(0)
excs = (Exception) except IndexError:
self.assertRaises(excs, self.action.execute) effect = None
self.mock.VerifyAll()
def _stop_db(self, reboot=True): if isinstance(effect, Exception):
self.guest.stop_db(do_not_start_on_reboot=reboot) raise effect
self.instance.datastore_status.status = ( elif effect is not None:
rd_instance.ServiceStatuses.SHUTDOWN) new_status, new_flavor_id = effect
def _server_changes_to(self, new_status, new_flavor_id):
def change():
self.server.status = new_status self.server.status = new_status
self.instance.server.flavor['id'] = new_flavor_id self.instance.server.flavor['id'] = new_flavor_id
if not self.poll_until_mocked: def _datastore_changes_to(self, new_status):
self.mock.StubOutWithMock(utils, "poll_until") self.instance.datastore_status.status = new_status
self.poll_until_mocked = True
utils.poll_until(mox.IgnoreArg(), sleep_time=2, time_out=120)\
.WithSideEffects(lambda ignore, sleep_time, time_out: change())
def _nova_resizes_successfully(self):
self.server.resize(NEW_FLAVOR_ID)
self._server_changes_to("VERIFY_RESIZE", NEW_FLAVOR_ID)
@test(groups=[GROUP, GROUP + '.resize']) @test(groups=[GROUP, GROUP + '.resize'])
@ -121,7 +107,7 @@ class ResizeTests(ResizeTestBase):
NEW_FLAVOR.__dict__) NEW_FLAVOR.__dict__)
def _start_mysql(self): def _start_mysql(self):
datastore = Mock(spec=DatastoreVersion) datastore = mock.Mock(spec=DatastoreVersion)
datastore.datastore_name = 'mysql' datastore.datastore_name = 'mysql'
datastore.name = 'mysql-5.7' datastore.name = 'mysql-5.7'
datastore.manager = 'mysql' datastore.manager = 'mysql'
@ -130,110 +116,249 @@ class ResizeTests(ResizeTestBase):
self.instance.guest.start_db_with_conf_changes(config.render()) self.instance.guest.start_db_with_conf_changes(config.render())
def test_guest_wont_stop_mysql(self): def test_guest_wont_stop_mysql(self):
self.guest.stop_db(do_not_start_on_reboot=True)\ self.guest.stop_db.side_effect = RPCException("Could not stop MySQL!")
.AndRaise(RPCException("Could not stop MySQL!")) self.assertRaises(RPCException, self.action.execute)
self.guest.stop_db.assert_called_once_with(do_not_start_on_reboot=True)
self.instance.update_db.assert_called_once_with(
task_status=InstanceTasks.NONE)
def test_nova_wont_resize(self): def test_nova_wont_resize(self):
self._stop_db() self._datastore_changes_to(rd_instance.ServiceStatuses.SHUTDOWN)
self.server.resize(NEW_FLAVOR_ID).AndRaise(BadRequest) self.server.resize.side_effect = BadRequest(400)
self.server.status = "ACTIVE" self.server.status = "ACTIVE"
self.guest.restart() self.assertRaises(BadRequest, self.action.execute)
self._execute_action() self.guest.stop_db.assert_called_once_with(do_not_start_on_reboot=True)
self.server.resize.assert_called_once_with(NEW_FLAVOR_ID)
self.guest.restart.assert_called_once()
self.instance.update_db.assert_called_once_with(
task_status=InstanceTasks.NONE)
def test_nova_resize_timeout(self): def test_nova_resize_timeout(self):
self._stop_db() self._datastore_changes_to(rd_instance.ServiceStatuses.SHUTDOWN)
self.server.resize(NEW_FLAVOR_ID) self.server.status = "ACTIVE"
self.mock.StubOutWithMock(utils, 'poll_until') with mock.patch.object(utils, 'poll_until') as mock_poll_until:
utils.poll_until(mox.IgnoreArg(), sleep_time=2, time_out=120) mock_poll_until.side_effect = [None, PollTimeOut()]
utils.poll_until(mox.IgnoreArg(), sleep_time=2, time_out=120)\ self.assertRaises(PollTimeOut, self.action.execute)
.AndRaise(PollTimeOut) expected_calls = [
self._execute_action() mock.call(mock.ANY, sleep_time=2, time_out=120)] * 2
self.assertEqual(expected_calls, mock_poll_until.call_args_list)
self.guest.stop_db.assert_called_once_with(
do_not_start_on_reboot=True)
self.server.resize.assert_called_once_with(NEW_FLAVOR_ID)
self.instance.update_db.assert_called_once_with(
task_status=InstanceTasks.NONE)
def test_nova_doesnt_change_flavor(self): def test_nova_doesnt_change_flavor(self):
self._stop_db() self._datastore_changes_to(rd_instance.ServiceStatuses.SHUTDOWN)
self.server.resize(NEW_FLAVOR_ID)
self._server_changes_to("VERIFY_RESIZE", OLD_FLAVOR_ID) with mock.patch.object(utils, 'poll_until') as mock_poll_until:
utils.poll_until(mox.IgnoreArg(), sleep_time=2, time_out=120) self.poll_until_side_effects.extend([
self.instance.guest.reset_configuration(mox.IgnoreArg()) ("VERIFY_RESIZE", OLD_FLAVOR_ID),
self.instance.server.revert_resize() None,
self._server_changes_to("ACTIVE", OLD_FLAVOR_ID) ("ACTIVE", OLD_FLAVOR_ID)])
self.guest.restart() mock_poll_until.side_effect = self._poll_until
self._execute_action()
self.assertRaisesRegex(TroveError,
"flavor_id=.* and not .*",
self.action.execute)
expected_calls = [
mock.call(mock.ANY, sleep_time=2, time_out=120)] * 3
self.assertEqual(expected_calls, mock_poll_until.call_args_list)
# Make sure self.poll_until_side_effects is empty
self.assertFalse(self.poll_until_side_effects)
self.guest.stop_db.assert_called_once_with(
do_not_start_on_reboot=True)
self.server.resize.assert_called_once_with(NEW_FLAVOR_ID)
self.instance.guest.reset_configuration.assert_called_once_with(
mock.ANY)
self.instance.server.revert_resize.assert_called_once()
self.guest.restart.assert_called_once()
self.instance.update_db.assert_called_once_with(
task_status=InstanceTasks.NONE)
def test_nova_resize_fails(self): def test_nova_resize_fails(self):
self._stop_db() self._datastore_changes_to(rd_instance.ServiceStatuses.SHUTDOWN)
self.server.resize(NEW_FLAVOR_ID)
self._server_changes_to("ERROR", OLD_FLAVOR_ID) with mock.patch.object(utils, 'poll_until') as mock_poll_until:
self._execute_action() self.poll_until_side_effects.extend([
None,
("ERROR", OLD_FLAVOR_ID)])
mock_poll_until.side_effect = self._poll_until
self.assertRaisesRegex(TroveError,
"status=ERROR and not VERIFY_RESIZE",
self.action.execute)
expected_calls = [
mock.call(mock.ANY, sleep_time=2, time_out=120)] * 2
self.assertEqual(expected_calls, mock_poll_until.call_args_list)
# Make sure self.poll_until_side_effects is empty
self.assertFalse(self.poll_until_side_effects)
self.guest.stop_db.assert_called_once_with(
do_not_start_on_reboot=True)
self.server.resize.assert_called_once_with(NEW_FLAVOR_ID)
self.instance.update_db.assert_called_once_with(
task_status=InstanceTasks.NONE)
def test_nova_resizes_in_weird_state(self): def test_nova_resizes_in_weird_state(self):
self._stop_db() self._datastore_changes_to(rd_instance.ServiceStatuses.SHUTDOWN)
self.server.resize(NEW_FLAVOR_ID)
self._server_changes_to("ACTIVE", NEW_FLAVOR_ID) with mock.patch.object(utils, 'poll_until') as mock_poll_until:
self.guest.restart() self.poll_until_side_effects.extend([
self._execute_action() None,
("ACTIVE", NEW_FLAVOR_ID)])
mock_poll_until.side_effect = self._poll_until
self.assertRaisesRegex(TroveError,
"status=ACTIVE and not VERIFY_RESIZE",
self.action.execute)
expected_calls = [
mock.call(mock.ANY, sleep_time=2, time_out=120)] * 2
self.assertEqual(expected_calls, mock_poll_until.call_args_list)
# Make sure self.poll_until_side_effects is empty
self.assertFalse(self.poll_until_side_effects)
self.guest.stop_db.assert_called_once_with(
do_not_start_on_reboot=True)
self.server.resize.assert_called_once_with(NEW_FLAVOR_ID)
self.guest.restart.assert_called_once()
self.instance.update_db.assert_called_once_with(
task_status=InstanceTasks.NONE)
def test_guest_is_not_okay(self): def test_guest_is_not_okay(self):
self._stop_db() self._datastore_changes_to(rd_instance.ServiceStatuses.SHUTDOWN)
self._nova_resizes_successfully()
utils.poll_until(mox.IgnoreArg(), sleep_time=2, time_out=120) with mock.patch.object(utils, 'poll_until') as mock_poll_until:
self.instance.set_datastore_status_to_paused() self.poll_until_side_effects.extend([
self.instance.datastore_status.status = ( None,
rd_instance.ServiceStatuses.PAUSED) ("VERIFY_RESIZE", NEW_FLAVOR_ID),
utils.poll_until(mox.IgnoreArg(), sleep_time=2, time_out=120)\ None,
.AndRaise(PollTimeOut) PollTimeOut(),
self.instance.guest.reset_configuration(mox.IgnoreArg()) ("ACTIVE", OLD_FLAVOR_ID)])
self.instance.server.revert_resize() mock_poll_until.side_effect = self._poll_until
self._server_changes_to("ACTIVE", OLD_FLAVOR_ID)
self.guest.restart() self.instance.set_datastore_status_to_paused.side_effect = (
self._execute_action() lambda: self._datastore_changes_to(
rd_instance.ServiceStatuses.PAUSED))
self.assertRaises(PollTimeOut, self.action.execute)
expected_calls = [
mock.call(mock.ANY, sleep_time=2, time_out=120)] * 5
self.assertEqual(expected_calls, mock_poll_until.call_args_list)
# Make sure self.poll_until_side_effects is empty
self.assertFalse(self.poll_until_side_effects)
self.guest.stop_db.assert_called_once_with(
do_not_start_on_reboot=True)
self.server.resize.assert_called_once_with(NEW_FLAVOR_ID)
self.instance.set_datastore_status_to_paused.assert_called_once()
self.instance.guest.reset_configuration.assert_called_once_with(
mock.ANY)
self.instance.server.revert_resize.assert_called_once()
self.guest.restart.assert_called_once()
self.instance.update_db.assert_called_once_with(
task_status=InstanceTasks.NONE)
def test_mysql_is_not_okay(self): def test_mysql_is_not_okay(self):
self._stop_db() self._datastore_changes_to(rd_instance.ServiceStatuses.SHUTDOWN)
self._nova_resizes_successfully()
utils.poll_until(mox.IgnoreArg(), sleep_time=2, time_out=120) with mock.patch.object(utils, 'poll_until') as mock_poll_until:
self.instance.set_datastore_status_to_paused() self.poll_until_side_effects.extend([
self.instance.datastore_status.status = ( None,
rd_instance.ServiceStatuses.SHUTDOWN) ("VERIFY_RESIZE", NEW_FLAVOR_ID),
utils.poll_until(mox.IgnoreArg(), sleep_time=2, time_out=120) PollTimeOut(),
self._start_mysql() ("ACTIVE", OLD_FLAVOR_ID)])
utils.poll_until(mox.IgnoreArg(), sleep_time=2, mock_poll_until.side_effect = self._poll_until
time_out=120).AndRaise(PollTimeOut)
self.instance.guest.reset_configuration(mox.IgnoreArg()) self.instance.set_datastore_status_to_paused.side_effect = (
self.instance.server.revert_resize() lambda: self._datastore_changes_to(
self._server_changes_to("ACTIVE", OLD_FLAVOR_ID) rd_instance.ServiceStatuses.SHUTDOWN))
self.guest.restart()
self._execute_action() self._start_mysql()
self.assertRaises(PollTimeOut, self.action.execute)
expected_calls = [
mock.call(mock.ANY, sleep_time=2, time_out=120)] * 4
self.assertEqual(expected_calls, mock_poll_until.call_args_list)
# Make sure self.poll_until_side_effects is empty
self.assertFalse(self.poll_until_side_effects)
self.guest.stop_db.assert_called_once_with(
do_not_start_on_reboot=True)
self.server.resize.assert_called_once_with(NEW_FLAVOR_ID)
self.instance.set_datastore_status_to_paused.assert_called_once()
self.instance.guest.reset_configuration.assert_called_once_with(
mock.ANY)
self.instance.server.revert_resize.assert_called_once()
self.guest.restart.assert_called_once()
self.instance.update_db.assert_called_once_with(
task_status=InstanceTasks.NONE)
def test_confirm_resize_fails(self): def test_confirm_resize_fails(self):
self._stop_db() self._datastore_changes_to(rd_instance.ServiceStatuses.SHUTDOWN)
self._nova_resizes_successfully()
utils.poll_until(mox.IgnoreArg(), sleep_time=2, time_out=120) with mock.patch.object(utils, 'poll_until') as mock_poll_until:
self.instance.set_datastore_status_to_paused() self.poll_until_side_effects.extend([
self.instance.datastore_status.status = ( None,
rd_instance.ServiceStatuses.RUNNING) ("VERIFY_RESIZE", NEW_FLAVOR_ID),
utils.poll_until(mox.IgnoreArg(), sleep_time=2, time_out=120) None,
self._start_mysql() None,
utils.poll_until(mox.IgnoreArg(), sleep_time=2, time_out=120) ("SHUTDOWN", NEW_FLAVOR_ID)])
self.server.status = "SHUTDOWN" mock_poll_until.side_effect = self._poll_until
self.instance.server.confirm_resize()
self._execute_action() self.instance.set_datastore_status_to_paused.side_effect = (
lambda: self._datastore_changes_to(
rd_instance.ServiceStatuses.RUNNING))
self.server.confirm_resize.side_effect = BadRequest(400)
self._start_mysql()
self.assertRaises(BadRequest, self.action.execute)
expected_calls = [
mock.call(mock.ANY, sleep_time=2, time_out=120)] * 5
self.assertEqual(expected_calls, mock_poll_until.call_args_list)
# Make sure self.poll_until_side_effects is empty
self.assertFalse(self.poll_until_side_effects)
self.guest.stop_db.assert_called_once_with(
do_not_start_on_reboot=True)
self.server.resize.assert_called_once_with(NEW_FLAVOR_ID)
self.instance.set_datastore_status_to_paused.assert_called_once()
self.instance.server.confirm_resize.assert_called_once()
self.instance.update_db.assert_called_once_with(
task_status=InstanceTasks.NONE)
def test_revert_nova_fails(self): def test_revert_nova_fails(self):
self._stop_db() self._datastore_changes_to(rd_instance.ServiceStatuses.SHUTDOWN)
self._nova_resizes_successfully()
utils.poll_until(mox.IgnoreArg(), sleep_time=2, time_out=120) with mock.patch.object(utils, 'poll_until') as mock_poll_until:
self.instance.set_datastore_status_to_paused() self.poll_until_side_effects.extend([
self.instance.datastore_status.status = ( None,
rd_instance.ServiceStatuses.PAUSED) ("VERIFY_RESIZE", NEW_FLAVOR_ID),
utils.poll_until(mox.IgnoreArg(), None,
sleep_time=2, PollTimeOut(),
time_out=120).AndRaise(PollTimeOut) ("ERROR", OLD_FLAVOR_ID)])
self.instance.guest.reset_configuration(mox.IgnoreArg()) mock_poll_until.side_effect = self._poll_until
self.instance.server.revert_resize()
self._server_changes_to("ERROR", OLD_FLAVOR_ID) self.instance.set_datastore_status_to_paused.side_effect = (
self._execute_action() lambda: self._datastore_changes_to(
rd_instance.ServiceStatuses.PAUSED))
self.assertRaises(PollTimeOut, self.action.execute)
expected_calls = [
mock.call(mock.ANY, sleep_time=2, time_out=120)] * 5
self.assertEqual(expected_calls, mock_poll_until.call_args_list)
# Make sure self.poll_until_side_effects is empty
self.assertFalse(self.poll_until_side_effects)
self.guest.stop_db.assert_called_once_with(
do_not_start_on_reboot=True)
self.server.resize.assert_called_once_with(NEW_FLAVOR_ID)
self.instance.set_datastore_status_to_paused.assert_called_once()
self.instance.guest.reset_configuration.assert_called_once_with(
mock.ANY)
self.instance.server.revert_resize.assert_called_once()
self.instance.update_db.assert_called_once_with(
task_status=InstanceTasks.NONE)
@test(groups=[GROUP, GROUP + '.migrate']) @test(groups=[GROUP, GROUP + '.migrate'])
@ -244,26 +369,32 @@ class MigrateTests(ResizeTestBase):
self._init() self._init()
self.action = models.MigrateAction(self.instance) self.action = models.MigrateAction(self.instance)
def _execute_action(self):
self.instance.update_db(task_status=InstanceTasks.NONE)
self.mock.ReplayAll()
self.assertIsNone(self.action.execute())
self.mock.VerifyAll()
def _start_mysql(self):
self.guest.restart()
def test_successful_migrate(self): def test_successful_migrate(self):
self.mock.StubOutWithMock(self.instance.server, 'migrate') self._datastore_changes_to(rd_instance.ServiceStatuses.SHUTDOWN)
self._stop_db()
self.server.migrate(force_host=None) with mock.patch.object(utils, 'poll_until') as mock_poll_until:
self._server_changes_to("VERIFY_RESIZE", NEW_FLAVOR_ID) self.poll_until_side_effects.extend([
utils.poll_until(mox.IgnoreArg(), sleep_time=2, time_out=120) None,
self.instance.set_datastore_status_to_paused() ("VERIFY_RESIZE", NEW_FLAVOR_ID),
self.instance.datastore_status.status = ( None,
rd_instance.ServiceStatuses.RUNNING) None])
utils.poll_until(mox.IgnoreArg(), sleep_time=2, time_out=120) mock_poll_until.side_effect = self._poll_until
self._start_mysql()
utils.poll_until(mox.IgnoreArg(), sleep_time=2, time_out=120) self.instance.set_datastore_status_to_paused.side_effect = (
self.instance.server.confirm_resize() lambda: self._datastore_changes_to(
self._execute_action() rd_instance.ServiceStatuses.RUNNING))
self.action.execute()
expected_calls = [
mock.call(mock.ANY, sleep_time=2, time_out=120)] * 4
self.assertEqual(expected_calls, mock_poll_until.call_args_list)
# Make sure self.poll_until_side_effects is empty
self.assertFalse(self.poll_until_side_effects)
self.guest.stop_db.assert_called_once_with(
do_not_start_on_reboot=True)
self.server.migrate.assert_called_once_with(force_host=None)
self.instance.set_datastore_status_to_paused.assert_called_once()
self.instance.server.confirm_resize.assert_called_once()
self.instance.update_db.assert_called_once_with(
task_status=InstanceTasks.NONE)