def process_manual_failover_from_leader(self) -> Optional[str]:
        """Checks if manual failover is requested and takes action if appropriate.

        Cleans up failover key if failover conditions are not matched.

        :returns: action message if demote was initiated, None if no action was taken"""
        failover = self.cluster.failover
        # if there is no failover key or
        # I am holding the lock but am not primary = I am the standby leader,
        # then do nothing
        if not failover or (self.is_paused() and not self.state_handler.is_primary()):
            return

        action = self._get_failover_action_name()
        bare_action = action.replace('manual ', '')

        # it is not the time for the scheduled switchover yet, do nothing
        if (failover.scheduled_at and not
            self.should_run_scheduled_action(bare_action, failover.scheduled_at, lambda:
                                             self.dcs.manual_failover('', '', version=failover.version))):
            return

        if not failover.leader or failover.leader == self.state_handler.name:
            if not failover.candidate or failover.candidate != self.state_handler.name:
                if not failover.candidate and self.is_paused():
                    logger.warning('%s is possible only to a specific candidate in a paused state', action.title())
                elif self.is_failover_possible():
                    ret = self._async_executor.try_run_async(f'{action}: demote', self.demote, ('graceful',))
                    return ret or f'{action}: demoting myself'
                else:
                    logger.warning('%s: no healthy members found, %s is not possible',
                                   action, bare_action)
            else:
                logger.warning('%s: I am already the leader, no need to %s', action, bare_action)
        else:
            logger.warning('%s: leader name does not match: %s != %s', action, failover.leader, self.state_handler.name)

        logger.info('Cleaning up failover key')
        self.dcs.manual_failover('', '', version=failover.version)
Checks if manual failover is requested and takes action if appropriate.

        Cleans up failover key if failover conditions are not matched.

        :returns: action message if demote was initiated, None if no action was taken
patroni/ha.py