Beispiel #1
0
 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)
Beispiel #2
0
 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)
Beispiel #3
0
 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)
Beispiel #4
0
 def delete_backup(self, context, backup_id):
     with EndNotification(context):
         models.BackupTasks.delete_backup(context, backup_id)
Beispiel #5
0
 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)
Beispiel #6
0
 def delete_database(self, context, database):
     with EndNotification(context):
         return self.mysql_admin().delete_database(database)
Beispiel #7
0
    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
Beispiel #8
0
 def delete_database(self, context, database):
     """Delete the specified database.
     """
     with EndNotification(context):
         self._drop_database(
             models.PostgreSQLSchema.deserialize_schema(database))
Beispiel #9
0
 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)
Beispiel #10
0
 def delete_user(self, context, user):
     LOG.debug("Deleting user.")
     with EndNotification(context):
         return service.MongoDBAdmin().delete_user(user)
Beispiel #11
0
 def create_backup(self, context, backup_info):
     LOG.debug("Creating backup.")
     with EndNotification(context):
         backup.backup(context, backup_info)
Beispiel #12
0
 def delete_database(self, context, database):
     LOG.debug("Deleting database.")
     with EndNotification(context):
         return service.MongoDBAdmin().delete_database(database)
Beispiel #13
0
 def create_user(self, context, users):
     LOG.debug("Creating user(s).")
     with EndNotification(context):
         return service.MongoDBAdmin().create_users(users)
Beispiel #14
0
 def create_database(self, context, databases):
     LOG.debug("Creating database(s).")
     with EndNotification(context):
         return service.MongoDBAdmin().create_database(databases)
Beispiel #15
0
 def create_database(self, context, databases):
     with EndNotification(context):
         return self.mysql_admin().create_database(databases)
Beispiel #16
0
 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)
Beispiel #17
0
 def create_user(self, context, users):
     with EndNotification(context):
         self.mysql_admin().create_user(users)
Beispiel #18
0
    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
Beispiel #19
0
 def delete_user(self, context, user):
     with EndNotification(context):
         self.mysql_admin().delete_user(user)
Beispiel #20
0
 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)
Beispiel #21
0
 def migrate(self, context, instance_id, host):
     with EndNotification(context):
         instance_tasks = models.BuiltInstanceTasks.load(
             context, instance_id)
         instance_tasks.migrate(host)
Beispiel #22
0
    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
Beispiel #23
0
 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)
Beispiel #25
0
 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)
Beispiel #26
0
 def change_passwords(self, context, users):
     with EndNotification(context):
         self.mysql_admin().change_passwords(users)
Beispiel #27
0
 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)
Beispiel #28
0
 def update_attributes(self, context, username, hostname, user_attrs):
     with EndNotification(context):
         self.mysql_admin().update_attributes(username, hostname,
                                              user_attrs)
Beispiel #29
0
 def reboot(self, context, instance_id):
     with EndNotification(context):
         instance_tasks = models.BuiltInstanceTasks.load(
             context, instance_id)
         instance_tasks.reboot()
Beispiel #30
0
 def change_passwords(self, context, users):
     LOG.debug("Changing password.")
     with EndNotification(context):
         return service.MongoDBAdmin().change_passwords(users)