def update_attributes(self, context, username, hostname, user_attrs): LOG.debug("Updating database attributes.") with EndNotification(context): return service.MongoDBAdmin().update_attributes( username, user_attrs)
def delete_cluster(self, context, cluster_id): with EndNotification(context): cluster_tasks = models.load_cluster_tasks(context, cluster_id) cluster_tasks.delete_cluster(context, cluster_id)
def resize_flavor(self, context, instance_id, old_flavor, new_flavor): with EndNotification(context): instance_tasks = models.BuiltInstanceTasks.load( context, instance_id) instance_tasks.resize_flavor(old_flavor, new_flavor)
def delete_backup(self, context, backup_id): with EndNotification(context): models.BackupTasks.delete_backup(context, backup_id)
def upgrade(self, context, instance_id, datastore_version_id): instance_tasks = models.BuiltInstanceTasks.load(context, instance_id) datastore_version = DatastoreVersion.load_by_uuid(datastore_version_id) with EndNotification(context): instance_tasks.upgrade(datastore_version)
def delete_database(self, context, database): with EndNotification(context): return self.mysql_admin().delete_database(database)
def eject_replica_source(self, context, instance_id): def _eject_replica_source(old_master, replica_models): master_candidate = self._most_current_replica( old_master, replica_models) master_ips = old_master.detach_public_ips() slave_ips = master_candidate.detach_public_ips() master_candidate.detach_replica(old_master, for_failover=True) master_candidate.enable_as_master() master_candidate.attach_public_ips(master_ips) master_candidate.make_read_only(False) old_master.attach_public_ips(slave_ips) exception_replicas = [] error_messages = "" for replica in replica_models: try: if replica.id != master_candidate.id: replica.detach_replica(old_master, for_failover=True) replica.attach_replica(master_candidate) except exception.TroveError as ex: msg = (_("Unable to migrate replica %(slave)s from " "old replica source %(old_master)s to " "new source %(new_master)s on eject.") % { "slave": replica.id, "old_master": old_master.id, "new_master": master_candidate.id }) LOG.exception(msg) exception_replicas.append(replica) error_messages += "%s (%s)\n" % (msg, ex) self._set_task_status([old_master] + replica_models, InstanceTasks.NONE) if exception_replicas: self._set_task_status(exception_replicas, InstanceTasks.EJECTION_ERROR) msg = ( _("eject-replica-source %(id)s: The following " "replicas may not have been switched: %(replicas)s:" "\n%(err)s") % { "id": master_candidate.id, "replicas": [repl.id for repl in exception_replicas], "err": error_messages }) raise ReplicationSlaveAttachError(msg) with EndNotification(context): master = BuiltInstanceTasks.load(context, instance_id) replicas = [ BuiltInstanceTasks.load(context, dbinfo.id) for dbinfo in master.slaves ] try: _eject_replica_source(master, replicas) except ReplicationSlaveAttachError: raise except Exception: self._set_task_status([master] + replicas, InstanceTasks.EJECTION_ERROR) raise
def delete_database(self, context, database): """Delete the specified database. """ with EndNotification(context): self._drop_database( models.PostgreSQLSchema.deserialize_schema(database))
def grow_cluster(self, context, cluster_id, new_instance_ids): with EndNotification(context, cluster_id=cluster_id, instance_ids=new_instance_ids): cluster_tasks = models.load_cluster_tasks(context, cluster_id) cluster_tasks.grow_cluster(context, cluster_id, new_instance_ids)
def delete_user(self, context, user): LOG.debug("Deleting user.") with EndNotification(context): return service.MongoDBAdmin().delete_user(user)
def create_backup(self, context, backup_info): LOG.debug("Creating backup.") with EndNotification(context): backup.backup(context, backup_info)
def delete_database(self, context, database): LOG.debug("Deleting database.") with EndNotification(context): return service.MongoDBAdmin().delete_database(database)
def create_user(self, context, users): LOG.debug("Creating user(s).") with EndNotification(context): return service.MongoDBAdmin().create_users(users)
def create_database(self, context, databases): LOG.debug("Creating database(s).") with EndNotification(context): return service.MongoDBAdmin().create_database(databases)
def create_database(self, context, databases): with EndNotification(context): return self.mysql_admin().create_database(databases)
def shrink_cluster(self, context, cluster_id, instance_ids): with EndNotification(context, cluster_id=cluster_id, instance_ids=instance_ids): cluster_tasks = models.load_cluster_tasks(context, cluster_id) cluster_tasks.shrink_cluster(context, cluster_id, instance_ids)
def create_user(self, context, users): with EndNotification(context): self.mysql_admin().create_user(users)
def promote_to_replica_source(self, context, instance_id): # TODO(atomic77) Promote and eject need to be able to handle the case # where a datastore like Postgresql needs to treat the slave to be # promoted differently from the old master and the slaves which will # be simply reassigned to a new master. See: # https://bugs.launchpad.net/trove/+bug/1553339 def _promote_to_replica_source(old_master, master_candidate, replica_models): # First, we transition from the old master to new as quickly as # possible to minimize the scope of unrecoverable error # NOTE(zhaochao): we cannot reattach the old master to the new # one immediately after the new master is up, because for MariaDB # the other replicas are still connecting to the old master, and # during reattaching the old master as a slave, new GTID may be # created and synced to the replicas. After that, when attaching # the replicas to the new master, 'START SLAVE' will fail by # 'fatal error 1236' if the binlog of the replica diverged from # the new master. So the proper order should be: # -1. make the old master read only (and detach floating ips) # -2. make sure the new master is up-to-date # -3. detach the new master from the old one # -4. enable the new master (and attach floating ips) # -5. attach the other replicas to the new master # -6. attach the old master to the new one # (and attach floating ips) # -7. demote the old master # What we changed here is the order of the 6th step, previously # this step took place right after step 4, which causes failures # with MariaDB replications. old_master.make_read_only(True) master_ips = old_master.detach_public_ips() slave_ips = master_candidate.detach_public_ips() latest_txn_id = old_master.get_latest_txn_id() master_candidate.wait_for_txn(latest_txn_id) master_candidate.detach_replica(old_master, for_failover=True) master_candidate.enable_as_master() master_candidate.attach_public_ips(master_ips) master_candidate.make_read_only(False) # At this point, should something go wrong, there # should be a working master with some number of working slaves, # and possibly some number of "orphaned" slaves exception_replicas = [] error_messages = "" for replica in replica_models: try: if replica.id != master_candidate.id: replica.detach_replica(old_master, for_failover=True) replica.attach_replica(master_candidate) except exception.TroveError as ex: log_fmt = ("Unable to migrate replica %(slave)s from " "old replica source %(old_master)s to " "new source %(new_master)s on promote.") exc_fmt = _("Unable to migrate replica %(slave)s from " "old replica source %(old_master)s to " "new source %(new_master)s on promote.") msg_content = { "slave": replica.id, "old_master": old_master.id, "new_master": master_candidate.id} LOG.exception(log_fmt, msg_content) exception_replicas.append(replica) error_messages += "%s (%s)\n" % ( exc_fmt % msg_content, ex) # dealing with the old master after all the other replicas # has been migrated. old_master.attach_replica(master_candidate) old_master.attach_public_ips(slave_ips) try: old_master.demote_replication_master() except Exception as ex: log_fmt = "Exception demoting old replica source %s." exc_fmt = _("Exception demoting old replica source %s.") LOG.exception(log_fmt, old_master.id) exception_replicas.append(old_master) error_messages += "%s (%s)\n" % ( exc_fmt % old_master.id, ex) self._set_task_status([old_master] + replica_models, InstanceTasks.NONE) if exception_replicas: self._set_task_status(exception_replicas, InstanceTasks.PROMOTION_ERROR) msg = (_("promote-to-replica-source %(id)s: The following " "replicas may not have been switched: %(replicas)s:" "\n%(err)s") % {"id": master_candidate.id, "replicas": [repl.id for repl in exception_replicas], "err": error_messages}) raise ReplicationSlaveAttachError(msg) with EndNotification(context): master_candidate = BuiltInstanceTasks.load(context, instance_id) old_master = BuiltInstanceTasks.load(context, master_candidate.slave_of_id) replicas = [] for replica_dbinfo in old_master.slaves: if replica_dbinfo.id == instance_id: replica = master_candidate else: replica = BuiltInstanceTasks.load(context, replica_dbinfo.id) replicas.append(replica) try: _promote_to_replica_source(old_master, master_candidate, replicas) except ReplicationSlaveAttachError: raise except Exception: self._set_task_status([old_master] + replicas, InstanceTasks.PROMOTION_ERROR) raise
def delete_user(self, context, user): with EndNotification(context): self.mysql_admin().delete_user(user)
def detach_replica(self, context, instance_id): with EndNotification(context): slave = models.BuiltInstanceTasks.load(context, instance_id) master_id = slave.slave_of_id master = models.BuiltInstanceTasks.load(context, master_id) slave.detach_replica(master)
def migrate(self, context, instance_id, host): with EndNotification(context): instance_tasks = models.BuiltInstanceTasks.load( context, instance_id) instance_tasks.migrate(host)
def promote_to_replica_source(self, context, instance_id): def _promote_to_replica_source(old_master, master_candidate, replica_models): # First, we transition from the old master to new as quickly as # possible to minimize the scope of unrecoverable error old_master.make_read_only(True) master_ips = old_master.detach_public_ips() slave_ips = master_candidate.detach_public_ips() latest_txn_id = old_master.get_latest_txn_id() master_candidate.wait_for_txn(latest_txn_id) master_candidate.detach_replica(old_master, for_failover=True) master_candidate.enable_as_master() old_master.attach_replica(master_candidate) master_candidate.attach_public_ips(master_ips) master_candidate.make_read_only(False) old_master.attach_public_ips(slave_ips) # At this point, should something go wrong, there # should be a working master with some number of working slaves, # and possibly some number of "orphaned" slaves exception_replicas = [] for replica in replica_models: try: if replica.id != master_candidate.id: replica.detach_replica(old_master, for_failover=True) replica.attach_replica(master_candidate) except exception.TroveError: msg = _("promote-to-replica-source: Unable to migrate " "replica %(slave)s from old replica source " "%(old_master)s to new source %(new_master)s.") msg_values = { "slave": replica.id, "old_master": old_master.id, "new_master": master_candidate.id } LOG.exception(msg % msg_values) exception_replicas.append(replica) try: old_master.demote_replication_master() except Exception: LOG.exception(_("Exception demoting old replica source")) exception_replicas.append(old_master) self._set_task_status([old_master] + replica_models, InstanceTasks.NONE) if exception_replicas: self._set_task_status(exception_replicas, InstanceTasks.PROMOTION_ERROR) msg = _("promote-to-replica-source %(id)s: The following " "replicas may not have been switched: %(replicas)s") msg_values = { "id": master_candidate.id, "replicas": exception_replicas } raise ReplicationSlaveAttachError(msg % msg_values) with EndNotification(context): master_candidate = BuiltInstanceTasks.load(context, instance_id) old_master = BuiltInstanceTasks.load(context, master_candidate.slave_of_id) replicas = [] for replica_dbinfo in old_master.slaves: if replica_dbinfo.id == instance_id: replica = master_candidate else: replica = BuiltInstanceTasks.load(context, replica_dbinfo.id) replicas.append(replica) try: _promote_to_replica_source(old_master, master_candidate, replicas) except ReplicationSlaveAttachError: raise except Exception: self._set_task_status([old_master] + replicas, InstanceTasks.PROMOTION_ERROR) raise
def create_backup(self, context, backup_info, instance_id): with EndNotification(context, backup_id=backup_info['id']): instance_tasks = models.BuiltInstanceTasks.load( context, instance_id) instance_tasks.create_backup(backup_info)
def _server_call(self, server_type): with patch.object(self.context, "notification", server_type=server_type) as notification: with EndNotification(self.context): pass self.assertTrue(notification.notify_end.called)
def create_cluster(self, context, cluster_id): with EndNotification(context, cluster_id=cluster_id): cluster_tasks = models.load_cluster_tasks(context, cluster_id) cluster_tasks.create_cluster(context, cluster_id)
def change_passwords(self, context, users): with EndNotification(context): self.mysql_admin().change_passwords(users)
def resize_volume(self, context, instance_id, new_size): with EndNotification(context): instance_tasks = models.BuiltInstanceTasks.load( context, instance_id) instance_tasks.resize_volume(new_size)
def update_attributes(self, context, username, hostname, user_attrs): with EndNotification(context): self.mysql_admin().update_attributes(username, hostname, user_attrs)
def reboot(self, context, instance_id): with EndNotification(context): instance_tasks = models.BuiltInstanceTasks.load( context, instance_id) instance_tasks.reboot()
def change_passwords(self, context, users): LOG.debug("Changing password.") with EndNotification(context): return service.MongoDBAdmin().change_passwords(users)