diff --git a/docs/reference.md b/docs/reference.md
index 61010363d8911c13c990f7856183fc596dfb9c1e..c1e6eb8511ab1af935be4dfebccbd0cee1823f3b 100644
--- a/docs/reference.md
+++ b/docs/reference.md
@@ -3318,6 +3318,19 @@ If you want more control over this process (Debian upgrades have been
 event-less for a while now, but it's not always been the case) you
 can of course run the upgrade manually.
 
+### Decommissioning a host
+
+When turning down a host, it is necessary, at some point, to
+reschedule the services that were there onto some other hosts. To
+achieve a smooth transition, this is best done while the host is still
+available.
+
+To do this, set the *turndown* attribute to *true* in the inventory
+for the host you want to turn down, and then run *float* once more.
+This should safely reschedule all services, and remove them from the
+target host. It is then possible to simply shut down the target host
+and wipe its data.
+
 # Example scenarios
 
 This section will look at some example scenarios and use cases for
diff --git a/docs/reference.pdf b/docs/reference.pdf
index 822b75c0e569b4280059734e474714e7b7ecade1..7a29260cc0f44d7f4bac04e7b096da388ecd8d67 100644
Binary files a/docs/reference.pdf and b/docs/reference.pdf differ
diff --git a/plugins/inventory/float.py b/plugins/inventory/float.py
index 46c2b25a0e4d0d1c53635da2e197e14f576963c9..e67df79ecb905ae7792d9ae24b952ab3ef688613 100644
--- a/plugins/inventory/float.py
+++ b/plugins/inventory/float.py
@@ -282,6 +282,16 @@ def _global_dns_map(inventory):
     return dns
 
 
+# Return the hosts that are not available for scheduling, as a
+# Python set.
+def _unavailable_hosts(inventory):
+    unavail = set()
+    for name, values in inventory['hosts'].items():
+        if values.get('turndown'):
+            unavail.add(name)
+    return unavail
+
+
 # Build a group -> hosts map out of an inventory.
 def _build_group_map(inventory, assignments=None):
     group_map = {}
@@ -499,7 +509,8 @@ class Assignments(object):
         return str(self._fwd)
 
     @classmethod
-    def _available_hosts(cls, service, group_map, service_hosts_map):
+    def _available_hosts(cls, service, group_map, service_hosts_map,
+                         unavailable_hosts={}):
         if 'schedule_with' in service:
             return service_hosts_map[service['schedule_with']]
         scheduling_groups = ['all']
@@ -512,7 +523,7 @@ class Assignments(object):
             if g not in group_map:
                 raise Exception(f'The scheduling_group "{g}" is not defined in inventoy')
             available_hosts.update(group_map[g])
-        return list(available_hosts)
+        return list(available_hosts.difference(unavailable_hosts))
 
     @classmethod
     def schedule(cls, services, inventory):
@@ -525,6 +536,7 @@ class Assignments(object):
         """
         service_hosts_map = {}
         service_master_map = {}
+        unavailable_hosts = _unavailable_hosts(inventory)
         group_map = _build_group_map(inventory)
         host_occupation = collections.defaultdict(int)
 
@@ -540,13 +552,16 @@ class Assignments(object):
         for service_name in sorted(services.keys(), key=_sort_key):
             service = services[service_name]
             available_hosts = cls._available_hosts(service, group_map,
-                                                   service_hosts_map)
+                                                   service_hosts_map,
+                                                   unavailable_hosts)
             num_instances = service.get('num_instances', 'all')
             if num_instances == 'all':
                 service_hosts = sorted(available_hosts)
             else:
                 service_hosts = sorted(_binpack(
                     available_hosts, host_occupation, num_instances))
+            if not service_hosts:
+                raise Exception(f'No hosts available to schedule service {service_name}')
             service_hosts_map[service_name] = service_hosts
             for h in service_hosts:
                 host_occupation[h] += 1