summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBo Tran <ministry.96.nd@gmail.com>2022-01-06 14:27:25 +0700
committerBo Tran <ministry.96.nd@gmail.com>2022-01-24 17:06:05 +0700
commit99df090a857f48ae27e9c361f6835fc2297a0498 (patch)
treebb679a7cee52c001150e39059df3fe1ef62461d1
parentbe86b79119d16ee77f596172f43b0c97cb2617bd (diff)
downloadtrove-99df090a857f48ae27e9c361f6835fc2297a0498.tar.gz
Adapt to file injection deprecation in nova
Story: #2009770 Task: #44247 Change-Id: I34d47e709a9a7478cb6a85d6e6e37da3f92e40b0
-rw-r--r--trove/common/cfg.py4
-rw-r--r--trove/instance/models.py40
-rwxr-xr-xtrove/taskmanager/models.py40
-rw-r--r--trove/tests/unittests/taskmanager/test_models.py44
4 files changed, 91 insertions, 37 deletions
diff --git a/trove/common/cfg.py b/trove/common/cfg.py
index eadb8514..65c030cf 100644
--- a/trove/common/cfg.py
+++ b/trove/common/cfg.py
@@ -23,9 +23,9 @@ from oslo_config import cfg
from oslo_config import types
from oslo_config.cfg import NoSuchOptError
from oslo_log import log as logging
+from oslo_log import versionutils
from oslo_middleware import cors
from osprofiler import opts as profiler
-from oslo_log import versionutils
from trove.common.i18n import _
from trove.version import version_info as version
@@ -245,7 +245,7 @@ common_opts = [
cfg.IntOpt('trove_conductor_workers',
help='Number of workers for the Conductor service. The default '
'will be the number of CPUs available.'),
- cfg.BoolOpt('use_nova_server_config_drive', default=True,
+ cfg.BoolOpt('use_nova_server_config_drive', default=False,
help='Use config drive for file injection when booting '
'instance.'),
cfg.StrOpt('device_path', default='/dev/vdb',
diff --git a/trove/instance/models.py b/trove/instance/models.py
index b2659d08..4691b6b9 100644
--- a/trove/instance/models.py
+++ b/trove/instance/models.py
@@ -15,12 +15,14 @@
# under the License.
"""Model classes that form the core of instances functionality."""
-from datetime import datetime
-from datetime import timedelta
+import base64
import json
import os.path
import re
+from datetime import datetime
+from datetime import timedelta
+
from novaclient import exceptions as nova_exceptions
from oslo_config.cfg import NoSuchOptError
from oslo_log import log as logging
@@ -43,8 +45,8 @@ from trove.common.i18n import _
from trove.common.trove_remote import create_trove_client
from trove.configuration.models import Configuration
from trove.datastore import models as datastore_models
-from trove.datastore.models import DatastoreVersionMetadata as dvm
from trove.datastore.models import DBDatastoreVersionMetadata
+from trove.datastore.models import DatastoreVersionMetadata as dvm
from trove.db import get_db_api
from trove.db import models as dbmodels
from trove.extensions.security_group.models import SecurityGroup
@@ -614,9 +616,10 @@ def load_instance(cls, context, id, needs_server=False,
def update_service_status(task_status, service_status, ins_id):
"""Update service status as needed."""
+ RESTART_REQUIRED = srvstatus.ServiceStatuses.RESTART_REQUIRED
if (task_status == InstanceTasks.NONE and
- service_status.status != srvstatus.ServiceStatuses.RESTART_REQUIRED and
- not service_status.is_uptodate()):
+ service_status.status != RESTART_REQUIRED and
+ not service_status.is_uptodate()):
LOG.warning('Guest agent heartbeat for instance %s has expried',
ins_id)
service_status.status = \
@@ -718,7 +721,8 @@ class BaseInstance(SimpleInstance):
from trove.cluster.models import is_cluster_deleting
if (self.db_info.cluster_id is not None and not
- is_cluster_deleting(self.context, self.db_info.cluster_id)):
+ is_cluster_deleting(context=self.context,
+ cluster_id=self.db_info.cluster_id)):
raise exception.ClusterInstanceOperationNotSupported()
if self.slaves:
@@ -963,6 +967,25 @@ class BaseInstance(SimpleInstance):
self._server_group_loaded = True
return self._server_group
+ def prepare_cloud_config(self, files):
+ userdata = (
+ "#cloud-config\n"
+ "write_files:\n"
+ )
+
+ for filename, content in files.items():
+ ud = encodeutils.safe_encode(content)
+ body_userdata = (
+ "- encoding: b64\n"
+ " owner: trove:trove\n"
+ " path: %s\n"
+ " content: %s\n" % (
+ filename, encodeutils.safe_decode(base64.b64encode(ud)))
+ )
+ userdata = userdata + body_userdata
+
+ return userdata
+
def get_injected_files(self, datastore_manager, datastore_version):
injected_config_location = CONF.get('injected_config_location')
guest_info = CONF.get('guest_info')
@@ -1034,12 +1057,14 @@ class BaseInstance(SimpleInstance):
class FreshInstance(BaseInstance):
+
@classmethod
def load(cls, context, id):
return load_instance(cls, context, id, needs_server=False)
class BuiltInstance(BaseInstance):
+
@classmethod
def load(cls, context, id, needs_server=True):
return load_instance(cls, context, id, needs_server=needs_server)
@@ -1509,7 +1534,7 @@ class Instance(BuiltInstance):
if not self.slaves:
raise exception.BadRequest(_("Instance %s is not a replica"
- " source.") % self.id)
+ " source.") % self.id)
service = InstanceServiceStatus.find_by(instance_id=self.id)
last_heartbeat_delta = timeutils.utcnow() - service.updated_at
@@ -1934,6 +1959,7 @@ class DBInstance(dbmodels.DatabaseModelBase):
class instance_encryption_key_cache(object):
+
def __init__(self, func, lru_cache_size=10):
self._table = {}
self._lru = []
diff --git a/trove/taskmanager/models.py b/trove/taskmanager/models.py
index 49742af8..134aecb5 100755
--- a/trove/taskmanager/models.py
+++ b/trove/taskmanager/models.py
@@ -229,8 +229,8 @@ class ClusterTasks(Cluster):
)
def _all_instances_acquire_status(
- self, instance_ids, cluster_id, shard_id, expected_status,
- fast_fail_statuses=None):
+ self, instance_ids, cluster_id, shard_id, expected_status,
+ fast_fail_statuses=None):
def _is_fast_fail_status(status):
return ((fast_fail_statuses is not None) and
@@ -244,7 +244,7 @@ class ClusterTasks(Cluster):
task_status = DBInstance.find_by(
id=instance_id).get_task_status()
if (_is_fast_fail_status(status) or
- (task_status == InstanceTasks.BUILDING_ERROR_SERVER)):
+ (task_status == InstanceTasks.BUILDING_ERROR_SERVER)):
# if one has failed, no need to continue polling
LOG.debug("Instance %(id)s has acquired a fast-fail "
"status %(status)s and"
@@ -269,7 +269,7 @@ class ClusterTasks(Cluster):
task_status = DBInstance.find_by(
id=instance_id).get_task_status()
if (_is_fast_fail_status(status) or
- (task_status == InstanceTasks.BUILDING_ERROR_SERVER)):
+ (task_status == InstanceTasks.BUILDING_ERROR_SERVER)):
failed_instance_ids.append(instance_id)
return failed_instance_ids
@@ -373,8 +373,8 @@ class ClusterTasks(Cluster):
context.notification = (
DBaaSInstanceUpgrade(context, **request_info))
with StartNotification(
- context, instance_id=instance.id,
- datastore_version_id=datastore_version.id):
+ context, instance_id=instance.id,
+ datastore_version_id=datastore_version.id):
with EndNotification(context):
instance.update_db(
datastore_version_id=datastore_version.id,
@@ -781,8 +781,8 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
status = service.get_status()
if (status == srvstatus.ServiceStatuses.RUNNING or
- status == srvstatus.ServiceStatuses.INSTANCE_READY or
- status == srvstatus.ServiceStatuses.HEALTHY):
+ status == srvstatus.ServiceStatuses.INSTANCE_READY or
+ status == srvstatus.ServiceStatuses.HEALTHY):
return True
elif status not in [srvstatus.ServiceStatuses.NEW,
srvstatus.ServiceStatuses.BUILDING,
@@ -986,6 +986,16 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
config_drive = CONF.use_nova_server_config_drive
key_name = CONF.nova_keypair
+ # Use config_drive instead by userdata
+ # We will inject guest config by cloud-config
+ if not config_drive:
+ if not userdata:
+ userdata = self.prepare_cloud_config(files)
+ else:
+ userdata = userdata + self.prepare_cloud_config(files)
+
+ files = {}
+
server = self.nova_client.servers.create(
self.name, image_id, flavor_id, key_name=key_name, nics=nics,
block_device_mapping_v2=bdmap_v2,
@@ -1432,6 +1442,7 @@ class BuiltInstanceTasks(Instance, NotifyMixin, ConfigurationMixin):
class BackupTasks(object):
+
@classmethod
def _parse_manifest(cls, manifest):
# manifest is in the format 'container/prefix'
@@ -1530,11 +1541,11 @@ class ModuleTasks(object):
for instance_module in instance_modules:
instance_id = instance_module.instance_id
if (instance_module.md5 != current_md5 or force) and (
- not md5 or md5 == instance_module.md5):
+ not md5 or md5 == instance_module.md5):
instance = BuiltInstanceTasks.load(context, instance_id,
needs_server=False)
if instance and (
- include_clustered or not instance.cluster_id):
+ include_clustered or not instance.cluster_id):
try:
module_models.Modules.validate(
modules, instance.datastore.id,
@@ -1550,8 +1561,8 @@ class ModuleTasks(object):
# Sleep if we've fired off too many in a row.
if (batch_size and
- not reapply_count % batch_size and
- (reapply_count + skipped_count) < total_count):
+ not reapply_count % batch_size and
+ (reapply_count + skipped_count) < total_count):
LOG.debug("Applied module to %(cnt)d of %(total)d "
"instances - sleeping for %(batch)ds",
{'cnt': reapply_count,
@@ -1908,7 +1919,7 @@ class ResizeActionBase(object):
self._perform_nova_action()
finally:
if self.instance.db_info.task_status != (
- inst_models.InstanceTasks.NONE):
+ inst_models.InstanceTasks.NONE):
self.instance.reset_task_status()
def _guest_is_awake(self):
@@ -1988,6 +1999,7 @@ class ResizeActionBase(object):
class ResizeAction(ResizeActionBase):
+
def __init__(self, instance, old_flavor, new_flavor):
"""
:type instance: trove.taskmanager.models.BuiltInstanceTasks
@@ -2043,6 +2055,7 @@ class ResizeAction(ResizeActionBase):
class MigrateAction(ResizeActionBase):
+
def __init__(self, instance, host=None):
super(MigrateAction, self).__init__(instance)
self.instance = instance
@@ -2070,6 +2083,7 @@ class MigrateAction(ResizeActionBase):
class RebuildAction(ResizeActionBase):
+
def __init__(self, instance, image_id):
"""The action to perform rebuild.
diff --git a/trove/tests/unittests/taskmanager/test_models.py b/trove/tests/unittests/taskmanager/test_models.py
index fde42e35..5167bc04 100644
--- a/trove/tests/unittests/taskmanager/test_models.py
+++ b/trove/tests/unittests/taskmanager/test_models.py
@@ -12,43 +12,46 @@
# License for the specific language governing permissions and limitations
# under the License.
import os
+
from tempfile import NamedTemporaryFile
from unittest import mock
-from unittest.mock import call
from unittest.mock import MagicMock
from unittest.mock import Mock
-from unittest.mock import patch
from unittest.mock import PropertyMock
+from unittest.mock import call
+from unittest.mock import patch
-from cinderclient import exceptions as cinder_exceptions
-from cinderclient.v3 import volumes as cinderclient_volumes
import cinderclient.v3.client as cinderclient
import neutronclient.v2_0.client as neutronclient
-from novaclient import exceptions as nova_exceptions
import novaclient.v2.flavors
import novaclient.v2.servers
+
+from cinderclient import exceptions as cinder_exceptions
+from cinderclient.v3 import volumes as cinderclient_volumes
+from novaclient import exceptions as nova_exceptions
from oslo_config import cfg
from swiftclient.client import ClientException
from testtools.matchers import Equals
from testtools.matchers import Is
+import trove.backup.models
+import trove.common.context
+import trove.common.template as template
+import trove.db.models
+import trove.guestagent.api
+
from trove import rpc
from trove.backup import models as backup_models
from trove.backup import state
-import trove.backup.models
+from trove.common import exception
from trove.common import timeutils
from trove.common import utils
-import trove.common.context
-from trove.common import exception
from trove.common.exception import GuestError
from trove.common.exception import PollTimeOut
from trove.common.exception import TroveError
-import trove.common.template as template
from trove.datastore import models as datastore_models
-import trove.db.models
from trove.extensions.common import models as common_models
from trove.extensions.mysql import models as mysql_models
-import trove.guestagent.api
from trove.instance.models import BaseInstance
from trove.instance.models import DBInstance
from trove.instance.models import InstanceServiceStatus
@@ -64,6 +67,7 @@ VOLUME_ID = 'volume-id-1'
class FakeOptGroup(object):
+
def __init__(self, tcp_ports=['3306', '3301-3307'],
udp_ports=[], icmp=False):
self.tcp_ports = tcp_ports
@@ -72,6 +76,7 @@ class FakeOptGroup(object):
class fake_Server(object):
+
def __init__(self):
self.id = None
self.name = None
@@ -108,6 +113,7 @@ class fake_ServerManager(object):
class fake_nova_client(object):
+
def __init__(self):
self.servers = fake_ServerManager()
@@ -236,7 +242,8 @@ class FreshInstanceTasksTest(BaseFreshInstanceTasksTest):
server = self.freshinstancetasks._create_server(
None, None, datastore_manager, None, None, None)
- self.assertEqual(server.userdata, self.userdata)
+ userdata = self.userdata + "#cloud-config\nwrite_files:\n"
+ self.assertEqual(server.userdata, userdata)
def test_create_instance_with_keypair(self):
cfg.CONF.set_override('nova_keypair', 'fake_keypair')
@@ -310,7 +317,8 @@ class FreshInstanceTasksTest(BaseFreshInstanceTasksTest):
def test_servers_create_block_device_mapping_v2(self,
mock_hostname,
mock_name):
- self.freshinstancetasks.prepare_userdata = Mock(return_value=None)
+ self.freshinstancetasks.prepare_userdata = Mock(
+ return_value="#cloud-config\nwrite_files:\n")
mock_nova_client = self.freshinstancetasks.nova_client = Mock()
mock_servers_create = mock_nova_client.servers.create
self.freshinstancetasks._create_server('fake-flavor', 'fake-image',
@@ -318,14 +326,18 @@ class FreshInstanceTasksTest(BaseFreshInstanceTasksTest):
meta = {'trove_project_id': self.freshinstancetasks.tenant_id,
'trove_user_id': 'test_user',
'trove_instance_id': self.freshinstancetasks.id}
+
+ userdata = self.freshinstancetasks.prepare_userdata('mysql')
+ userdata = userdata + \
+ self.freshinstancetasks.prepare_cloud_config({})
mock_servers_create.assert_called_with(
'fake-name', 'fake-image',
'fake-flavor', files={},
- userdata=None,
+ userdata=userdata,
block_device_mapping_v2=None,
availability_zone=None,
nics=None,
- config_drive=True,
+ config_drive=False,
scheduler_hints=None,
key_name=None,
meta=meta,
@@ -599,6 +611,7 @@ class ResizeVolumeTest(trove_testtools.TestCase):
self.new_vol_size)
class FakeGroup(object):
+
def __init__(self):
self.mount_point = 'var/lib/mysql'
self.device_path = '/dev/vdb'
@@ -1105,6 +1118,7 @@ class BackupTasksTest(trove_testtools.TestCase):
class NotifyMixinTest(trove_testtools.TestCase):
+
def test_get_service_id(self):
id_map = {
'mysql': '123',