summaryrefslogtreecommitdiff
path: root/trove/instance/models.py
diff options
context:
space:
mode:
Diffstat (limited to 'trove/instance/models.py')
-rw-r--r--trove/instance/models.py172
1 files changed, 114 insertions, 58 deletions
diff --git a/trove/instance/models.py b/trove/instance/models.py
index 5cc53ec5..0621c2cc 100644
--- a/trove/instance/models.py
+++ b/trove/instance/models.py
@@ -1282,11 +1282,6 @@ class Instance(BuiltInstance):
Raises exception if a configuration assign cannot
currently be performed
"""
- # check if the instance already has a configuration assigned
- if self.db_info.configuration_id:
- raise exception.ConfigurationAlreadyAttached(
- instance_id=self.id,
- configuration_id=self.db_info.configuration_id)
# check if the instance is not ACTIVE or has tasks
status = None
@@ -1299,23 +1294,118 @@ class Instance(BuiltInstance):
raise exception.InvalidInstanceState(instance_id=self.id,
status=status)
- def unassign_configuration(self):
- LOG.debug("Unassigning the configuration from the instance %s.",
- self.id)
+ def attach_configuration(self, configuration_id):
+ LOG.debug("Attaching configuration to instance: %s", self.id)
+ if not self.db_info.configuration_id:
+ self._validate_can_perform_assign()
+ LOG.debug("Attaching configuration: %s", configuration_id)
+ config = Configuration.find(self.context, configuration_id,
+ self.db_info.datastore_version_id)
+ self.update_configuration(config)
+ else:
+ raise exception.ConfigurationAlreadyAttached(
+ instance_id=self.id,
+ configuration_id=self.db_info.configuration_id)
+
+ def update_configuration(self, configuration):
+ self.save_configuration(configuration)
+ return self.apply_configuration(configuration)
+
+ def save_configuration(self, configuration):
+ """Save configuration changes on the guest.
+ Update Trove records if successful.
+ This method does not update runtime values. It sets the instance task
+ to RESTART_REQUIRED.
+ """
+
+ LOG.debug("Saving configuration on instance: %s", self.id)
+ overrides = configuration.get_configuration_overrides()
+
+ # Always put the instance into RESTART_REQUIRED state after
+ # configuration update. The sate may be released only once (and if)
+ # the configuration is successfully applied.
+ # This ensures that the instance will always be in a consistent state
+ # even if the apply never executes or fails.
+ LOG.debug("Persisting new configuration on the guest.")
+ self.guest.update_overrides(overrides)
+ LOG.debug("Configuration has been persisted on the guest.")
+
+ # Configuration has now been persisted on the instance an can be safely
+ # detached. Update our records to reflect this change irrespective of
+ # results of any further operations.
+ self.update_db(task_status=InstanceTasks.RESTART_REQUIRED,
+ configuration_id=configuration.configuration_id)
+
+ def apply_configuration(self, configuration):
+ """Apply runtime configuration changes and release the
+ RESTART_REQUIRED task.
+ Apply changes only if ALL values can be applied at once.
+ Return True if the configuration has changed.
+ """
+
+ LOG.debug("Applying configuration on instance: %s", self.id)
+ overrides = configuration.get_configuration_overrides()
+
+ if not configuration.does_configuration_need_restart():
+ LOG.debug("Applying runtime configuration changes.")
+ self.guest.apply_overrides(overrides)
+ LOG.debug("Configuration has been applied.")
+ self.update_db(task_status=InstanceTasks.NONE)
+
+ return True
+
+ LOG.debug(
+ "Configuration changes include non-dynamic settings and "
+ "will require restart to take effect.")
+
+ return False
+
+ def detach_configuration(self):
+ LOG.debug("Detaching configuration from instance: %s", self.id)
if self.configuration and self.configuration.id:
- LOG.debug("Unassigning the configuration id %s.",
- self.configuration.id)
+ self._validate_can_perform_assign()
+ LOG.debug("Detaching configuration: %s", self.configuration.id)
+ self.remove_configuration()
+ else:
+ LOG.debug("No configuration found on instance.")
+
+ def remove_configuration(self):
+ configuration_id = self.delete_configuration()
+ return self.reset_configuration(configuration_id)
+
+ def delete_configuration(self):
+ """Remove configuration changes from the guest.
+ Update Trove records if successful.
+ This method does not update runtime values. It sets the instance task
+ to RESTART_REQUIRED.
+ Return ID of the removed configuration group.
+ """
+ LOG.debug("Deleting configuration from instance: %s", self.id)
+ configuration_id = self.configuration.id
+
+ LOG.debug("Removing configuration from the guest.")
+ self.guest.update_overrides({}, remove=True)
+ LOG.debug("Configuration has been removed from the guest.")
+
+ self.update_db(task_status=InstanceTasks.RESTART_REQUIRED,
+ configuration_id=None)
- self.guest.update_overrides({}, remove=True)
+ return configuration_id
- # Dynamically reset the configuration values back to their default
- # values from the configuration template.
- # Reset the values only if the default is available for all of
- # them and restart is not required by any.
- # Mark the instance with a 'RESTART_REQUIRED' status otherwise.
+ def reset_configuration(self, configuration_id):
+ """Dynamically reset the configuration values back to their default
+ values from the configuration template and release the
+ RESTART_REQUIRED task.
+ Reset the values only if the default is available for all of
+ them and restart is not required by any.
+ Return True if the configuration has changed.
+ """
+
+ LOG.debug("Resetting configuration on instance: %s", self.id)
+ if configuration_id:
flavor = self.get_flavor()
default_config = self._render_config_dict(flavor)
- current_config = Configuration(self.context, self.configuration.id)
+ current_config = Configuration(self.context, configuration_id)
current_overrides = current_config.get_configuration_overrides()
# Check the configuration template has defaults for all modified
# values.
@@ -1323,56 +1413,22 @@ class Instance(BuiltInstance):
for key in current_overrides.keys())
if (not current_config.does_configuration_need_restart() and
has_defaults_for_all):
+ LOG.debug("Applying runtime configuration changes.")
self.guest.apply_overrides(
{k: v for k, v in default_config.items()
if k in current_overrides})
+ LOG.debug("Configuration has been applied.")
+ self.update_db(task_status=InstanceTasks.NONE)
+
+ return True
else:
LOG.debug(
"Could not revert all configuration changes dynamically. "
"A restart will be required.")
- self.update_db(task_status=InstanceTasks.RESTART_REQUIRED)
else:
- LOG.debug("No configuration found on instance. Skipping.")
-
- def assign_configuration(self, configuration_id):
- self._validate_can_perform_assign()
-
- try:
- configuration = Configuration.load(self.context, configuration_id)
- except exception.ModelNotFoundError:
- raise exception.NotFound(
- message='Configuration group id: %s could not be found.'
- % configuration_id)
-
- config_ds_v = configuration.datastore_version_id
- inst_ds_v = self.db_info.datastore_version_id
- if (config_ds_v != inst_ds_v):
- raise exception.ConfigurationDatastoreNotMatchInstance(
- config_datastore_version=config_ds_v,
- instance_datastore_version=inst_ds_v)
-
- config = Configuration(self.context, configuration.id)
- LOG.debug("Config is %s.", config)
-
- self.update_overrides(config)
- self.update_db(configuration_id=configuration.id)
+ LOG.debug("There are no values to reset.")
- def update_overrides(self, config):
- LOG.debug("Updating or removing overrides for instance %s.", self.id)
-
- overrides = config.get_configuration_overrides()
- self.guest.update_overrides(overrides)
-
- # Apply the new configuration values dynamically to the running
- # datastore service.
- # Apply overrides only if ALL values can be applied at once or mark
- # the instance with a 'RESTART_REQUIRED' status.
- if not config.does_configuration_need_restart():
- self.guest.apply_overrides(overrides)
- else:
- LOG.debug("Configuration overrides has non-dynamic settings and "
- "will require restart to take effect.")
- self.update_db(task_status=InstanceTasks.RESTART_REQUIRED)
+ return False
def _render_config_dict(self, flavor):
config = template.SingleInstanceConfigTemplate(