summaryrefslogtreecommitdiff
path: root/trove
diff options
context:
space:
mode:
authorLingxian Kong <anlin.kong@gmail.com>2020-11-05 09:44:57 +1300
committerLingxian Kong <anlin.kong@gmail.com>2020-11-08 19:15:13 +1300
commit59a972b312c8d25ffb46b4a994374490731747ea (patch)
tree0c60a9ffcd8019a878c8bc7d914070aa11ccdab5 /trove
parentde056b912b617182953ebbc55240da00dfb56e73 (diff)
downloadtrove-59a972b312c8d25ffb46b4a994374490731747ea.tar.gz
Fix upgrading instance datastore version
Change-Id: I0456688c2e6c72b0312f1f79bb3e68f13fd2cb6e
Diffstat (limited to 'trove')
-rw-r--r--trove/guestagent/datastore/mysql_common/service.py5
-rw-r--r--trove/guestagent/utils/docker.py8
-rw-r--r--trove/instance/service.py9
-rw-r--r--trove/tests/unittests/instance/test_service.py48
4 files changed, 70 insertions, 0 deletions
diff --git a/trove/guestagent/datastore/mysql_common/service.py b/trove/guestagent/datastore/mysql_common/service.py
index d3d44bbc..50e5ebe7 100644
--- a/trove/guestagent/datastore/mysql_common/service.py
+++ b/trove/guestagent/datastore/mysql_common/service.py
@@ -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)
diff --git a/trove/guestagent/utils/docker.py b/trove/guestagent/utils/docker.py
index da3ad412..0fdda049 100644
--- a/trove/guestagent/utils/docker.py
+++ b/trove/guestagent/utils/docker.py
@@ -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)}")
diff --git a/trove/instance/service.py b/trove/instance/service.py
index 3884f9e3..86da146b 100644
--- a/trove/instance/service.py
+++ b/trove/instance/service.py
@@ -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)
diff --git a/trove/tests/unittests/instance/test_service.py b/trove/tests/unittests/instance/test_service.py
index e2635654..07444a4c 100644
--- a/trove/tests/unittests/instance/test_service.py
+++ b/trove/tests/unittests/instance/test_service.py
@@ -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)