'Allocate set of ips over IPAM.
If any single ip allocation fails, tries to deallocate all
allocated ip addresses.'

def _ipam_allocate_ips(self, context, ipam_driver, port, ips, revert_on_fail=True):

    allocated = []
    ips.sort(key=(lambda x: ('ip_address' not in x)))
    try:
        for ip in ips:
            ip_list = ([ip] if isinstance(ip, dict) else ip)
            subnets = [ip_dict['subnet_id'] for ip_dict in ip_list]
            try:
                factory = ipam_driver.get_address_request_factory()
                ip_request = factory.get_request(context, port, ip_list[0])
                ipam_allocator = ipam_driver.get_allocator(subnets)
                (ip_address, subnet_id) = ipam_allocator.allocate(ip_request)
            except ipam_exc.IpAddressGenerationFailureAllSubnets:
                raise n_exc.IpAddressGenerationFailure(net_id=port['network_id'])
            allocated.append({'ip_address': ip_address, 'subnet_id': subnet_id})
    except Exception:
        with excutils.save_and_reraise_exception():
            if (not ipam_driver.needs_rollback()):
                return
            LOG.debug('An    exception    occurred    during    IP    allocation.')
            if (revert_on_fail and allocated):
                LOG.debug('Reverting    allocation')
                self._safe_rollback(self._ipam_deallocate_ips, context, ipam_driver, port, allocated, revert_on_fail=False)
            elif ((not revert_on_fail) and ips):
                addresses = ',    '.join(self._get_failed_ips(ips, allocated))
                LOG.error(_LE('IP    allocation    failed    on    external    system    for    %s'), addresses)
    return allocated
