Fix upgrading instance datastore version

Change-Id: I0456688c2e6c72b0312f1f79bb3e68f13fd2cb6e
This commit is contained in:
Lingxian Kong 2020-11-05 09:44:57 +13:00
parent de056b912b
commit 59a972b312
4 changed files with 70 additions and 0 deletions

View File

@ -801,6 +801,8 @@ class BaseMySqlApp(service.BaseDbApp):
def upgrade(self, upgrade_info):
"""Upgrade the database."""
new_version = upgrade_info.get('datastore_version')
if new_version == CONF.datastore_version:
return
LOG.info('Stopping db container for upgrade')
self.stop_db()
@ -808,6 +810,9 @@ class BaseMySqlApp(service.BaseDbApp):
LOG.info('Deleting db container for upgrade')
docker_util.remove_container(self.docker_client)
LOG.info('Remove unused images before starting new db container')
docker_util.prune_images(self.docker_client)
LOG.info('Starting new db container with version %s for upgrade',
new_version)
self.start_db(update_db=True, ds_version=new_version)

View File

@ -151,3 +151,11 @@ def get_container_logs(client, name='database', tail=50):
container = client.containers.get(name)
output = container.logs(tail=tail)
return _decode_output(output)
def prune_images(client):
"""Remove unused images."""
try:
client.images.prune(filters={'dangling': False})
except Exception as e:
LOG.warning(f"Prune image failed, error: {str(e)}")

View File

@ -528,6 +528,12 @@ class InstanceController(wsgi.Controller):
elif 'datastore_version' in kwargs:
datastore_version = ds_models.DatastoreVersion.load(
instance.datastore, kwargs['datastore_version'])
if datastore_version.name == instance.ds_version.name:
LOG.warning(f"Same datastore version {datastore_version.name} "
f"for upgrading")
return
context.notification = (
notification.DBaaSInstanceUpgrade(context, request=req))
with StartNotification(context, instance_id=instance.id,
@ -575,6 +581,9 @@ class InstanceController(wsgi.Controller):
if 'access' in body['instance']:
args['access'] = body['instance']['access']
if 'datastore_version' in body['instance']:
args['datastore_version'] = body['instance']['datastore_version']
self._modify_instance(context, req, instance, **args)
return wsgi.Result(None, 202)

View File

@ -15,7 +15,9 @@ from unittest import mock
from trove.common import clients
from trove.datastore import models as ds_models
from trove.instance import models as ins_models
from trove.instance import service
from trove.instance import service_status as srvstatus
from trove.tests.unittests import trove_testtools
from trove.tests.unittests.util import util
@ -51,6 +53,10 @@ class TestInstanceController(trove_testtools.TestCase):
super(TestInstanceController, cls).tearDownClass()
def setUp(self):
trove_testtools.patch_notifier(self)
super(TestInstanceController, self).setUp()
@mock.patch.object(clients, 'create_glance_client')
@mock.patch('trove.instance.models.Instance.create')
def test_create_by_ds_version_image_tags(self, mock_model_create,
@ -78,3 +84,45 @@ class TestInstanceController(trove_testtools.TestCase):
filters={'tag': ['trove', 'mysql'], 'status': 'active'},
sort='created_at:desc', limit=1
)
@mock.patch.object(clients, 'create_nova_client',
return_value=mock.MagicMock())
@mock.patch('trove.rpc.get_client')
def test_update_datastore_version(self, mock_get_rpc_client,
mock_create_nova_client):
# Create an instance in db.
instance = ins_models.DBInstance.create(
name=self.random_name('instance'),
flavor_id=self.random_uuid(),
tenant_id=self.random_uuid(),
volume_size=1,
datastore_version_id=self.ds_version_imageid.id,
task_status=ins_models.InstanceTasks.BUILDING,
compute_instance_id=self.random_uuid()
)
ins_models.InstanceServiceStatus.create(
instance_id=instance.id,
status=srvstatus.ServiceStatuses.NEW
)
# Create a new datastore version in db.
new_version_name = self.random_name('version')
ds_models.update_datastore_version(
self.ds_name, new_version_name,
'mysql', self.random_uuid(), [], '', 1
)
new_ds_version = ds_models.DatastoreVersion.load(
self.ds, new_version_name)
body = {
'instance': {
'datastore_version': new_ds_version.id
}
}
self.controller.update(mock.MagicMock(), instance.id, body, mock.ANY)
rpc_ctx = mock_get_rpc_client.return_value.prepare.return_value
rpc_ctx.cast.assert_called_once_with(
mock.ANY, "upgrade",
instance_id=instance.id,
datastore_version_id=new_ds_version.id)