def release_hosting_device_slots(self, context, hosting_device, resource,
                                     num):
        """Free <num> slots in <hosting_device> from logical resource <id>.

        Returns True if deallocation was successful. False otherwise.
        """
        with context.session.begin(subtransactions=True):
            num_str = str(num) if num >= 0 else "all"
            res_info = {'resource': resource}
            slot_info, query = self._get_or_create_slot_allocation(
                context, hosting_device, res_info, create=False)
            if slot_info is None:
                LOG.debug('Rejecting de-allocation of %(num)s slots in '
                          'hosting device %(device)s for logical resource '
                          '%(id)s', {'num': num_str,
                                     'device': hosting_device['id'],
                                     'id': resource['id']})
                return False
            if num >= 0:
                new_allocation = slot_info.num_allocated - num
            else:
                # if a negative num is specified all slot allocations for
                # the logical resource in the hosting device is removed
                new_allocation = 0
            if new_allocation < 0:
                LOG.debug('Rejecting de-allocation of %(num)s slots in '
                          'hosting device %(device)s for logical resource '
                          '%(id)s since only %(alloc)d slots are allocated.',
                          {'num': num_str, 'device': hosting_device['id'],
                           'id': resource['id'],
                           'alloc': slot_info.num_allocated})
                self._dispatch_pool_maintenance_job(hosting_device['template'])
                return False
            elif new_allocation == 0:
                result = query.delete()
                LOG.info('De-allocated %(num)s slots from hosting device '
                         '%(hd_id)s. %(total)d slots are now allocated in '
                         'that hosting device.',
                         {'num': num_str, 'total': new_allocation,
                          'hd_id': hosting_device['id']})
                if (hosting_device['tenant_bound'] is not None and
                    context.session.query(hd_models.SlotAllocation).filter_by(
                        hosting_device_id=hosting_device['id']).first() is
                        None):
                    # make hosting device tenant unbound if no logical
                    # resource use it anymore
                    hosting_device['tenant_bound'] = None
                    context.session.add(hosting_device)
                    LOG.info('Making hosting device %(hd_id)s with no '
                             'allocated slots tenant unbound.',
                             {'hd_id': hosting_device['id']})
                self._dispatch_pool_maintenance_job(hosting_device['template'])
                return result == 1
            LOG.info('De-allocated %(num)s slots from hosting device '
                     '%(hd_id)s. %(total)d slots are now allocated in '
                     'that hosting device.',
                     {'num': num_str, 'total': new_allocation,
                      'hd_id': hosting_device['id']})
            slot_info.num_allocated = new_allocation
            context.session.add(slot_info)
        self._dispatch_pool_maintenance_job(hosting_device['template'])
        # report success
        return True
Free <num> slots in <hosting_device> from logical resource <id>.

        Returns True if deallocation was successful. False otherwise.