Merge "Consider datastore version when generating configs"

This commit is contained in:
Jenkins
2014-05-23 00:15:16 +00:00
committed by Gerrit Code Review
7 changed files with 85 additions and 44 deletions

View File

@@ -38,36 +38,53 @@ class SingleInstanceConfigTemplate(object):
rendering on the guest
"""
template_name = "%s/config.template"
template_name = "config.template"
def __init__(self, datastore_manager, flavor_dict, instance_id):
def __init__(self, datastore_version, flavor_dict, instance_id):
"""Constructor
:param datastore_manager: The datastore manager.
:type name: str.
:param datastore_version: The datastore version.
:type datastore_version: DatastoreVersion
:param flavor_dict: dict containing flavor details for use in jinja.
:type flavor_dict: dict.
:param instance_id: trove instance id
:type: instance_id: str
:type instance_id: str
"""
self.flavor_dict = flavor_dict
template_filename = self.template_name % datastore_manager
self.template = ENV.get_template(template_filename)
self.datastore_manager = datastore_manager
self.datastore_version = datastore_version
#TODO(tim.simpson): The current definition of datastore_version is a
# bit iffy and I believe will change soon, so I'm
# creating a dictionary here for jinja to consume
# rather than pass in the datastore version object.
self.datastore_dict = {
'name': self.datastore_version.datastore_name,
'manager': self.datastore_version.manager,
'version': self.datastore_version.name,
}
self.instance_id = instance_id
def get_template(self):
patterns = ['{name}/{version}/{template_name}',
'{name}/{template_name}',
'{manager}/{template_name}']
context = self.datastore_dict.copy()
context['template_name'] = self.template_name
names = [name.format(**context) for name in patterns]
return ENV.select_template(names)
def render(self, **kwargs):
"""Renders the jinja template
:returns: str -- The rendered configuration file
"""
template = ENV.get_template(self.template_name %
self.datastore_manager)
template = self.get_template()
server_id = self._calculate_unique_id()
self.config_contents = template.render(
flavor=self.flavor_dict, server_id=server_id, **kwargs)
flavor=self.flavor_dict,
datastore=self.datastore_dict,
server_id=server_id, **kwargs)
return self.config_contents
def render_dict(self):
@@ -76,10 +93,10 @@ class SingleInstanceConfigTemplate(object):
to apply the default configuration dynamically.
"""
config = self.render()
cfg_parser = SERVICE_PARSERS.get(self.datastore_manager)
cfg_parser = SERVICE_PARSERS.get(self.datastore_version.manager)
if not cfg_parser:
raise exception.NoConfigParserFound(
datastore_manager=self.datastore_manager)
datastore_manager=self.datastore_version.manager)
return cfg_parser(config).parse()
def _calculate_unique_id(self):
@@ -92,7 +109,7 @@ class SingleInstanceConfigTemplate(object):
class OverrideConfigTemplate(SingleInstanceConfigTemplate):
template_name = "%s/override.config.template"
template_name = "override.config.template"
def load_heat_template(datastore_manager):

View File

@@ -97,6 +97,7 @@ class DatastoreVersion(object):
def __init__(self, db_info):
self.db_info = db_info
self._datastore_name = None
@classmethod
def load(cls, datastore, id_or_name):
@@ -127,6 +128,14 @@ class DatastoreVersion(object):
def datastore_id(self):
return self.db_info.datastore_id
@property
def datastore_name(self):
if self._datastore_name is None:
self._datastore_name = Datastore.load(self.datastore_id).name
return self._datastore_name
#TODO(tim.simpson): This would be less confusing if it was called "version"
# and datastore_name was called "name".
@property
def name(self):
return self.db_info.name

View File

@@ -707,7 +707,7 @@ class Instance(BuiltInstance):
flavor = self.get_flavor()
LOG.debug("flavor: %s" % flavor)
config = template.SingleInstanceConfigTemplate(
self.ds_version.manager, flavor, id)
self.ds_version, flavor, id)
return config.render_dict()
def resize_flavor(self, new_flavor_id):

View File

@@ -139,22 +139,21 @@ class ConfigurationMixin(object):
Configuration related tasks for instances and resizes.
"""
def _render_config(self, datastore_manager, flavor, instance_id):
def _render_config(self, flavor):
config = template.SingleInstanceConfigTemplate(
datastore_manager, flavor, instance_id)
self.datastore_version, flavor, self.id)
config.render()
return config
def _render_override_config(self, datastore_manager, flavor, instance_id,
overrides=None):
def _render_override_config(self, flavor, overrides=None):
config = template.OverrideConfigTemplate(
datastore_manager, flavor, instance_id)
self.datastore_version, flavor, self.id)
config.render(overrides=overrides)
return config
def _render_config_dict(self, datastore_manager, flavor, instance_id):
def _render_config_dict(self, flavor):
config = template.SingleInstanceConfigTemplate(
datastore_manager, flavor, instance_id)
self.datastore_version, flavor, self.id)
ret = config.render_dict()
LOG.debug("the default template dict of mysqld section: %s" % ret)
return ret
@@ -213,10 +212,8 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
availability_zone,
nics)
config = self._render_config(datastore_manager, flavor, self.id)
config_overrides = self._render_override_config(datastore_manager,
None,
self.id,
config = self._render_config(flavor)
config_overrides = self._render_override_config(flavor,
overrides=overrides)
backup_info = None
@@ -823,10 +820,10 @@ class BuiltInstanceTasks(BuiltInstance, NotifyMixin, ConfigurationMixin):
status = inst_models.InstanceTasks.RESTART_REQUIRED
self.update_db(task_status=status)
flavor = self.nova_client.flavors.get(self.flavor_id)
config_overrides = self._render_override_config(
self.ds_version.manager,
None,
self.id,
flavor,
overrides=overrides)
try:
self.guest.update_overrides(config_overrides.config_contents,
@@ -864,9 +861,7 @@ class BuiltInstanceTasks(BuiltInstance, NotifyMixin, ConfigurationMixin):
}
return str(int(digits) * conversions[size])
default_config = self._render_config_dict(self.ds_version.manager,
flavor,
self.id)
default_config = self._render_config_dict(flavor)
args = {
"ds_manager": self.ds_version.manager,
"config": default_config,
@@ -976,7 +971,7 @@ class BackupTasks(object):
backup.delete()
class ResizeVolumeAction(ConfigurationMixin):
class ResizeVolumeAction(object):
"""Performs volume resize action."""
def __init__(self, instance, old_size, new_size):
@@ -1200,7 +1195,7 @@ class ResizeVolumeAction(ConfigurationMixin):
raise TroveError(msg)
class ResizeActionBase(ConfigurationMixin):
class ResizeActionBase(object):
"""Base class for executing a resize action."""
def __init__(self, instance):
@@ -1385,11 +1380,7 @@ class ResizeAction(ResizeActionBase):
% self.instance.id)
LOG.debug("Repairing config.")
try:
config = self._render_config(
self.instance.datastore_version.manager,
self.old_flavor,
self.instance.id
)
config = self.instance._render_config(self.old_flavor)
config = {'config_contents': config.config_contents}
self.instance.guest.reset_configuration(config)
except GuestTimeout:
@@ -1411,8 +1402,7 @@ class ResizeAction(ResizeActionBase):
server=self.instance.server)
def _start_datastore(self):
config = self._render_config(self.instance.datastore_version.manager,
self.new_flavor, self.instance.id)
config = self.instance._render_config(self.new_flavor)
self.instance.guest.start_db_with_conf_changes(config.config_contents)

View File

@@ -0,0 +1 @@
hyper = 0M

View File

@@ -14,6 +14,7 @@
# under the License.
import mox
from mock import Mock
from testtools import TestCase
from proboscis import test
@@ -25,6 +26,7 @@ from trove.common import template
from trove.common import utils
from trove.common.context import TroveContext
from trove.common import instance as rd_instance
from trove.datastore.models import DatastoreVersion
from trove.guestagent import api as guest
from trove.instance.models import DBInstance
from trove.instance.models import InstanceServiceStatus
@@ -120,8 +122,12 @@ class ResizeTests(ResizeTestBase):
NEW_FLAVOR.__dict__)
def _start_mysql(self):
datastore = Mock(spec=DatastoreVersion)
datastore.datastore_name = 'mysql'
datastore.name = 'mysql-5.6'
datastore.manager = 'mysql'
config = template.SingleInstanceConfigTemplate(
"mysql", NEW_FLAVOR.__dict__, self.instance.id)
datastore, NEW_FLAVOR.__dict__, self.instance.id)
self.instance.guest.start_db_with_conf_changes(config.render())
def test_guest_wont_stop_mysql(self):

View File

@@ -11,11 +11,13 @@
#limitations under the License.
from mock import Mock
import testtools
import re
from trove.common import template
from trove.common import exception
from trove.datastore.models import DatastoreVersion
from trove.tests.unittests.util import util
@@ -25,7 +27,7 @@ class TemplateTest(testtools.TestCase):
util.init_db()
self.env = template.ENV
self.template = self.env.get_template("mysql/config.template")
self.flavor_dict = {'ram': 1024}
self.flavor_dict = {'ram': 1024, 'name': 'small', 'id': '55'}
self.server_id = "180b5ed1-3e57-4459-b7a3-2aeee4ac012a"
def tearDown(self):
@@ -56,12 +58,28 @@ class TemplateTest(testtools.TestCase):
self.server_id)
def test_single_instance_config_rendering(self):
config = template.SingleInstanceConfigTemplate('mysql',
datastore = Mock(spec=DatastoreVersion)
datastore.datastore_name = 'MySql'
datastore.name = 'mysql-5.6'
datastore.manager = 'mysql'
config = template.SingleInstanceConfigTemplate(datastore,
self.flavor_dict,
self.server_id)
self.validate_template(config.render(), "query_cache_size",
self.flavor_dict, self.server_id)
def test_renderer_discovers_special_config(self):
"""Finds our special config file for the version 'mysql-test'."""
datastore = Mock(spec=DatastoreVersion)
datastore.datastore_name = 'mysql'
datastore.name = 'mysql-test'
datastore.manager = 'mysql'
config = template.SingleInstanceConfigTemplate(datastore,
self.flavor_dict,
self.server_id)
self.validate_template(config.render(), "hyper",
{'ram': 0}, self.server_id)
class HeatTemplateLoadTest(testtools.TestCase):