def execute(self, server_id, allocate_public_ip, config):
        logging.info("Allocate IP for server %s" % server_id)

        novaclient = get_openstack_nova_client(config)
        neutronclient = get_openstack_neutron_client(config)

        retries = 0
        while novaclient.servers.get(server_id).status is "BUILDING" or not novaclient.servers.get(server_id).networks:
            logging.debug("...waiting for server to be ready")
            time.sleep(5)
            retries += 1
            if retries > 30:
                raise RuntimeError('Server %s is stuck in building' % server_id)

        server = novaclient.servers.get(server_id)
        if allocate_public_ip:

            ips = neutronclient.list_floatingips()
            allocated_from_pool = False
            free_ips = [ip for ip in ips["floatingips"] if ip["status"] != "ACTIVE"]
            if not free_ips:
                logging.debug("No allocated free IPs left, trying to allocate one")
                try:
                    # for backwards compatibility reasons we assume the
                    # network is called "public"
                    network_id = neutronclient.find_resource("network",
                                                             "public")
                    ip = neutronclient.create_floatingip({
                        "floating_network_id": network_id})
                    allocated_from_pool = True
                except neutronclient.exceptions.ClientException as e:
                    logging.warning("Cannot allocate IP, quota exceeded?")
                    raise e
            else:
                ip = free_ips[0]["floating_ip_address"]
                logging.info("IP assigned IS %s" % ip)
            try:
                server.add_floating_ip(ip)
            except Exception as e:
                logging.error(e)

            address_data = {
                'public_ip': ip,
                'allocated_from_pool': allocated_from_pool,
                'private_ip': list(server.networks.values())[0][0],
            }
        else:
            address_data = {
                'public_ip': None,
                'allocated_from_pool': False,
                'private_ip': list(server.networks.values())[0][0],
            }

        return address_data