text: from hetzner import RobotError
  
  __all__ = ['Failover', 'FailoverManager']
  
  
  class Failover(object):
      ip = None
      server_ip = None
      server_number = None
      active_server_ip = None
  
      def __repr__(self):
          return "%s (destination: %s, booked on %s (%s))" % (
              self.ip, self.active_server_ip, self.server_number, self.server_ip)
  
      def __init__(self, data):
          for attr, value in data.items():
              if hasattr(self, attr):
                  setattr(self, attr, value)
  
  
  class FailoverManager(object):
      def __init__(self, conn, servers):
          self.conn = conn
          self.servers = servers
  
      def list(self):
          failovers = {}
          try:
              ips = self.conn.get('/failover')
          except RobotError as err:
              if err.status == 404:
                  return failovers
              else:
                  raise
          for ip in ips:
              failover = Failover(ip.get('failover'))
              failovers[failover.ip] = failover
          return failovers
  
      def set(self, ip, new_destination):
          failovers = self.list()
          if ip not in failovers.keys():
              raise RobotError(
                  "Invalid IP address '%s'. Failover IP addresses are %s"
                  % (ip, failovers.keys()))
          failover = failovers.get(ip)
          if new_destination == failover.active_server_ip:
              raise RobotError(
                  "%s is already the active destination of failover IP %s"
                  % (new_destination, ip))
          available_dests = [s.ip for s in list(self.servers)]
          if new_destination not in available_dests:
              raise RobotError(
                  "Invalid destination '%s'. "
                  "The destination is not in your server list: %s"
                  % (new_destination, available_dests))
          result = self.conn.post('/failover/%s'
                                  % ip, {'active_server_ip': new_destination})
          return Failover(result.get('failover'))
  