Beispiel #1
0
    def stop_instances(self, request, queryset):
        """
        Stop all transmitted PostgreSQL instances

        This function assumes we're running against a bunch of Debian-based
        systems so we can use pg_ctlcluster. Thus far, that's the case. Later
        revisions may change that assumption.

        Skip already stopped services.
        """

        for inst in queryset:
            if not inst.is_online:
                self.message_user(request, "%s is already stopped." % inst,
                    messages.WARNING
                )
                continue

            try:
                util = PGUtility(inst)
                util.stop()

            except Exception, e:
                self.message_user(request, "%s : %s" % (e, inst), messages.ERROR)
                continue

            self.message_user(request, "%s stopped!" % inst)
Beispiel #2
0
    def restart_instances(self, request, queryset):
        """
        Restart all transmitted PostgreSQL instances

        Basicaly we just call for a fast stop followed by a start. Nothing
        complicated here. Unlike stop, we don't skip stopped instances, and
        unline start, we don't skip running ones.
        """

        for inst in queryset:
            try:
                util = PGUtility(inst)
                util.stop()
                util.start()

            except Exception, e:
                self.message_user(request, "%s : %s" % (e, inst), messages.ERROR)
                continue

            self.message_user(request, "%s restarted!" % inst)
Beispiel #3
0
    def restart_instances(self, request, queryset):
        """
        Restart all transmitted PostgreSQL instances

        Basicaly we just call for a fast stop followed by a start. Nothing
        complicated here. Unlike stop, we don't skip stopped instances, and
        unline start, we don't skip running ones.
        """

        for inst in queryset:
            try:
                util = PGUtility(inst)
                util.stop()
                util.start()

            except Exception, e:
                self.message_user(request, "%s : %s" % (e, inst), messages.ERROR)
                continue

            self.message_user(request, "%s restarted!" % inst)
Beispiel #4
0
    def stop_instances(self, request, queryset):
        """
        Stop all transmitted PostgreSQL instances

        Skip already stopped services.
        """

        for inst in queryset:
            if not inst.is_online:
                self.message_user(request, "%s is already stopped." % inst,
                    messages.WARNING
                )
                continue

            try:
                util = PGUtility(inst)
                util.stop()

            except Exception, e:
                self.message_user(request, "%s : %s" % (e, inst), messages.ERROR)
                continue

            self.message_user(request, "%s stopped!" % inst)
Beispiel #5
0
    def stop_instances(self, request, queryset):
        """
        Stop all transmitted PostgreSQL instances

        Skip already stopped services.
        """

        for inst in queryset:
            if not inst.is_online:
                self.message_user(request, "%s is already stopped." % inst,
                                  messages.WARNING)
                continue

            try:
                util = PGUtility(inst)
                util.stop()

            except Exception, e:
                self.message_user(request, "%s : %s" % (e, inst),
                                  messages.ERROR)
                continue

            self.message_user(request, "%s stopped!" % inst)
Beispiel #6
0
    def failover_pair(self, request, queryset):
        """
        Promote a Herd Follower to Leader Status

        This process is fairly complicated, and comes in several parts:

        1. Stop the current primary node. This ensures only the secondary
           can accept new data.
        2. Promote the top follower to read/write status. This essentially
           makes it the new leader of the herd.
        3. Assign the follower as the new stream source to the old primary.
           This officially swaps the roles of the two nodes. Note that the
           new follower is still out of sync with the new leader. This will
           require a separate node rebuild step to rectify.
        4. Move the declared virtual host to the new leader.
        5. Reassign all replicas to follow the new leader. We do this last
           because it relies on DNS propagation, and pushing a reload after
           that step implies a reconnection.
        """

        # Go to the confirmation form. As usual, this is fairly important,
        # so make sure the template is extremely descriptive regarding the
        # failover process.

        if request.POST.get('post') != 'yes':

            return render(request, 'admin/haas/disasterrecovery/failover.html', 
                    {'queryset' : queryset,
                     'opts': self.model._meta,
                     'action_checkbox_name': admin.ACTION_CHECKBOX_NAME,
                    }
            )

        # Since the form has been submitted, start swapping DR pairs.

        for dr_id in request.POST.getlist(admin.ACTION_CHECKBOX_NAME):
            newb = Instance.objects.get(pk=dr_id)
            sage = newb.master

            # Start with the transfer: stop -> promote -> alter.
            # Add in a short pause between to allow xlog propagation.

            try:
                sage_util = PGUtility(sage)
                newb_util = PGUtility(newb)

                sage_util.stop()
                sleep(5)
                newb_util.promote()

                sage.master = newb
                sage.save()

            except Exception, e:
                self.message_user(request,
                    "%s : %s" % (e, newb), messages.ERROR
                )
                continue

            # Now update the DNS. We'll just use the basic dnspython
            # module and load it with nameserver defaults. That should
            # be more than enough to propagate this change.

            try:
                def_dns = dns.resolver.get_default_resolver()

                new_dns = dns.update.Update(str(def_dns.domain).rstrip('.'))
                new_dns.delete(str(newb.herd.vhost), 'cname')
                new_dns.add(
                    str(newb.herd.vhost), '300', 'cname',
                    str(newb.server.hostname)
                )

                for ns in def_dns.nameservers:
                    dns.query.tcp(new_dns, ns)

            except Exception, e:
                self.message_user(request,
                    "%s : %s" % (e, newb), messages.ERROR
                )
                continue
Beispiel #7
0
    def failover_pair(self, request, queryset):
        """
        Promote a Herd Follower to Leader Status

        This process is fairly complicated, and comes in several parts:

        1. Stop the current primary node. This ensures only the secondary
           can accept new data.
        2. Promote the top follower to read/write status. This essentially
           makes it the new leader of the herd.
        3. Assign the follower as the new stream source to the old primary.
           This officially swaps the roles of the two nodes. Note that the
           new follower is still out of sync with the new leader. This will
           require a separate node rebuild step to rectify.
        4. Move the declared virtual host to the new leader.
        5. Reassign all replicas to follow the new leader. We do this last
           because it relies on DNS propagation, and pushing a reload after
           that step implies a reconnection.
        """

        # Go to the confirmation form. As usual, this is fairly important,
        # so make sure the template is extremely descriptive regarding the
        # failover process.

        if request.POST.get('post') != 'yes':

            return render(
                request, 'admin/haas/disasterrecovery/failover.html', {
                    'queryset': queryset,
                    'opts': self.model._meta,
                    'action_checkbox_name': admin.ACTION_CHECKBOX_NAME,
                })

        # Since the form has been submitted, start swapping DR pairs.

        for dr_id in request.POST.getlist(admin.ACTION_CHECKBOX_NAME):
            newb = Instance.objects.get(pk=dr_id)
            sage = newb.master

            # Start with the transfer: stop -> promote -> alter.
            # Add in a short pause between to allow xlog propagation.

            try:
                sage_util = PGUtility(sage)
                newb_util = PGUtility(newb)

                sage_util.stop()
                sleep(5)
                newb_util.promote()

                sage.master = newb
                sage.save()

            except Exception, e:
                self.message_user(request, "%s : %s" % (e, newb),
                                  messages.ERROR)
                continue

            # Now update the DNS. We'll just use the basic dnspython
            # module and load it with nameserver defaults. That should
            # be more than enough to propagate this change.

            try:
                def_dns = dns.resolver.get_default_resolver()

                new_dns = dns.update.Update(str(def_dns.domain).rstrip('.'))
                new_dns.delete(str(newb.herd.vhost), 'cname')
                new_dns.add(str(newb.herd.vhost), '300', 'cname',
                            str(newb.server.hostname))

                for ns in def_dns.nameservers:
                    dns.query.tcp(new_dns, ns)

            except Exception, e:
                self.message_user(request, "%s : %s" % (e, newb),
                                  messages.ERROR)
                continue