org.openbaton.clients.interfaces.client.openstack.OpenstackClient.java Source code

Java tutorial

Introduction

Here is the source code for org.openbaton.clients.interfaces.client.openstack.OpenstackClient.java

Source

/*
 *
 *  *
 *  *  * Copyright (c) 2016 Open Baton (http://www.openbaton.org)
 *  *  *
 *  *  * Licensed under the Apache License, Version 2.0 (the "License");
 *  *  * you may not use this file except in compliance with the License.
 *  *  * You may obtain a copy of the License at
 *  *  *
 *  *  *     http://www.apache.org/licenses/LICENSE-2.0
 *  *  *
 *  *  * Unless required by applicable law or agreed to in writing, software
 *  *  * distributed under the License is distributed on an "AS IS" BASIS,
 *  *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  *  * See the License for the specific language governing permissions and
 *  *  * limitations under the License.
 *  *
 *
 */

package org.openbaton.clients.interfaces.client.openstack;

import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableSet;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.TypeLiteral;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.util.SubnetUtils;
import org.jclouds.ContextBuilder;
import org.jclouds.collect.PagedIterable;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.domain.Credentials;
import org.jclouds.io.Payload;
import org.jclouds.io.payloads.ByteArrayPayload;
import org.jclouds.io.payloads.InputStreamPayload;
import org.jclouds.logging.slf4j.config.SLF4JLoggingModule;
import org.jclouds.openstack.glance.v1_0.GlanceApi;
import org.jclouds.openstack.glance.v1_0.domain.ContainerFormat;
import org.jclouds.openstack.glance.v1_0.domain.DiskFormat;
import org.jclouds.openstack.glance.v1_0.domain.ImageDetails;
import org.jclouds.openstack.glance.v1_0.features.ImageApi;
import org.jclouds.openstack.glance.v1_0.options.CreateImageOptions;
import org.jclouds.openstack.glance.v1_0.options.ListImageOptions;
import org.jclouds.openstack.glance.v1_0.options.UpdateImageOptions;
import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
import org.jclouds.openstack.keystone.v2_0.domain.Access;
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
import org.jclouds.openstack.neutron.v2.NeutronApi;
import org.jclouds.openstack.neutron.v2.domain.ExternalGatewayInfo;
import org.jclouds.openstack.neutron.v2.domain.FloatingIP;
import org.jclouds.openstack.neutron.v2.domain.IP;
import org.jclouds.openstack.neutron.v2.domain.Network.CreateNetwork;
import org.jclouds.openstack.neutron.v2.domain.Network.UpdateNetwork;
import org.jclouds.openstack.neutron.v2.domain.Port;
import org.jclouds.openstack.neutron.v2.domain.Router;
import org.jclouds.openstack.neutron.v2.domain.RouterInterface;
import org.jclouds.openstack.neutron.v2.domain.Subnet.CreateSubnet;
import org.jclouds.openstack.neutron.v2.domain.Subnet.UpdateSubnet;
import org.jclouds.openstack.neutron.v2.extensions.FloatingIPApi;
import org.jclouds.openstack.neutron.v2.extensions.RouterApi;
import org.jclouds.openstack.neutron.v2.features.NetworkApi;
import org.jclouds.openstack.neutron.v2.features.PortApi;
import org.jclouds.openstack.neutron.v2.features.SubnetApi;
import org.jclouds.openstack.nova.v2_0.NovaApi;
import org.jclouds.openstack.nova.v2_0.domain.Address;
import org.jclouds.openstack.nova.v2_0.domain.RebootType;
import org.jclouds.openstack.nova.v2_0.features.FlavorApi;
import org.jclouds.openstack.nova.v2_0.features.ServerApi;
import org.jclouds.openstack.nova.v2_0.options.CreateServerOptions;
import org.jclouds.openstack.v2_0.domain.Resource;
import org.jclouds.openstack.v2_0.options.PaginationOptions;
import org.jclouds.scriptbuilder.ScriptBuilder;
import org.jclouds.scriptbuilder.domain.OsFamily;
import org.openbaton.catalogue.mano.common.DeploymentFlavour;
import org.openbaton.catalogue.nfvo.NFVImage;
import org.openbaton.catalogue.nfvo.Network;
import org.openbaton.catalogue.nfvo.Quota;
import org.openbaton.catalogue.nfvo.Server;
import org.openbaton.catalogue.nfvo.Subnet;
import org.openbaton.catalogue.nfvo.VimInstance;
import org.openbaton.exceptions.VimDriverException;
import org.openbaton.plugin.PluginStarter;
import org.openbaton.vim.drivers.interfaces.VimDriver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.lang.reflect.InvocationTargetException;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URI;
import java.net.URL;
import java.net.UnknownHostException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.regex.Pattern;

import static org.jclouds.scriptbuilder.domain.Statements.exec;

/**
 * Created by mpa on 06.05.15.
 */
public class OpenstackClient extends VimDriver {

    private static final Pattern PATTERN = Pattern
            .compile("^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
    Iterable<Module> modules;
    Properties overrides;
    private static Logger log = LoggerFactory.getLogger(OpenstackClient.class);
    private static Lock lock;
    private Gson gson = new GsonBuilder().create();

    public OpenstackClient() throws RemoteException {
        super();
        init();
    }

    public static boolean validate(final String ip) {
        return PATTERN.matcher(ip).matches();
    }

    public static void main(String[] args) throws NoSuchMethodException, IOException, InstantiationException,
            TimeoutException, IllegalAccessException, InvocationTargetException {
        OpenstackClient.lock = new ReentrantLock();
        if (args.length == 6) {
            PluginStarter.registerPlugin(OpenstackClient.class, args[0], args[1], Integer.parseInt(args[2]),
                    Integer.parseInt(args[3]), args[4], args[5]);
        } else if (args.length == 4) {
            PluginStarter.registerPlugin(OpenstackClient.class, args[0], args[1], Integer.parseInt(args[2]),
                    Integer.parseInt(args[3]));
        } else {
            PluginStarter.registerPlugin(OpenstackClient.class, "openstack", "localhost", 5672, 10);
        }
        /*OpenstackClient client = new OpenstackClient();
        client.init();
        VimInstance vimInstance = new VimInstance();
        vimInstance.setUsername("openbaton");
        vimInstance.setPassword("openbaton");
        vimInstance.setTenant("slice-low-latency");
        vimInstance.setAuthUrl("http://172.27.101.16:5000/v2.0");
        vimInstance.setName("orange-box");
            
        try {
          System.out.println(client.listFreeFloatingIps(vimInstance));
        } catch (VimDriverException e) {
          e.printStackTrace();
        }*/
    }

    public void init() {
        modules = ImmutableSet.<Module>of(new SLF4JLoggingModule());
        overrides = new Properties();
        overrides.setProperty(KeystoneProperties.CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
        String sslChecksDisabled = properties.getProperty("disable-ssl-certificate-checks", "false");
        log.debug("Disable SSL certificate checks: {}", sslChecksDisabled);
        if (sslChecksDisabled.trim().equals("true")) {
            DisableSSLValidation.disableChecks();
        }
    }

    private String getZone(VimInstance vimInstance) {
        NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova").endpoint(vimInstance.getAuthUrl())
                .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(), vimInstance.getPassword())
                .modules(modules).overrides(overrides).buildApi(NovaApi.class);
        Set<String> zones = novaApi.getConfiguredRegions();
        log.debug("Available openstack environment zones: " + zones);
        String zone = null;
        if (vimInstance.getLocation() != null) {
            if (vimInstance.getLocation().getName() != null) {
                log.debug("Finding Location of openstack environment: " + vimInstance.getLocation().getName());
                for (String region : zones) {
                    if (region.equals(vimInstance.getLocation().getName())) {
                        zone = region;
                        log.debug("Found Location of openstack environment: " + zone);
                        break;
                    }
                }
                if (zone == null) {
                    log.warn("Not found Location '" + vimInstance.getLocation().getName()
                            + "'of openstack environment. Selecting a random one...");
                }
            } else {
                log.warn(
                        "Location of openstack environment is not defined properly -> Missing Name of the Location. Selecting a "
                                + "random one...");
            }
        } else {
            log.debug("Location of openstack environment is not defined. Selecting a random one...");
        }
        if (zone == null) {
            for (String zn : zones) {
                if (zn.contains("nova")) {
                    return zn;
                }
            }
            log.debug("Selecting a random Location of openstack environment from: " + zones);
            zone = zones.iterator().next();
            log.debug("Selected Location of openstack environment: '" + zone + "'");
        }
        return zone;
    }

    @Override
    public Server launchInstance(VimInstance vimInstance, String name, String imageId, String flavorId,
            String keypair, Set<String> network, Set<String> secGroup, String userData) throws VimDriverException {
        try {
            NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NovaApi.class);
            ServerApi serverApi = novaApi.getServerApi(getZone(vimInstance));
            String script = new ScriptBuilder().addStatement(exec(userData)).render(OsFamily.UNIX);
            CreateServerOptions options;
            if (keypair.equals("")) {
                options = CreateServerOptions.Builder.networks(network).securityGroupNames(secGroup)
                        .userData(script.getBytes());

            } else {

                options = CreateServerOptions.Builder.keyPairName(keypair).networks(network)
                        .securityGroupNames(secGroup).userData(script.getBytes());
            }

            log.debug("Keypair: " + keypair + ", SecGroup, " + secGroup + ", imageId: " + imageId + ", flavorId: "
                    + flavorId + ", networks: " + network);
            String extId = serverApi.create(name, imageId, flavorId, options).getId();
            Server server = getServerById(vimInstance, extId);
            log.debug("Created Server: " + server);
            return server;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    public Server launchInstanceAndWait(VimInstance vimInstance, String name, String imageId, String flavorId,
            String keypair, Set<String> network, Set<String> secGroup, String userData) throws VimDriverException {
        return launchInstanceAndWait(vimInstance, name, imageId, flavorId, keypair, network, secGroup, userData,
                null, null);
    }

    @Override
    public Server launchInstanceAndWait(VimInstance vimInstance, String name, String imageId, String flavorId,
            String keypair, Set<String> network, Set<String> secGroup, String userData,
            Map<String, String> floatingIp, Set<org.openbaton.catalogue.security.Key> keys)
            throws VimDriverException {
        boolean bootCompleted = false;
        if (keys != null && !keys.isEmpty()) {
            userData = addKeysToUserData(userData, keys);
        }
        log.info("Deploying VM on VimInstance: " + vimInstance.getName());
        log.debug("UserData is:\n " + userData + " \n");
        Server server = launchInstance(vimInstance, name, imageId, flavorId, keypair, network, secGroup, userData);
        log.info("Deployed VM ( " + server.getName() + " ) with extId: " + server.getExtId() + " in status "
                + server.getStatus());
        while (bootCompleted == false) {
            log.debug("Waiting for VM with hostname: " + name + " to finish the launch");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            server = getServerById(vimInstance, server.getExtId());
            if (server.getStatus().equals("ACTIVE")) {
                log.debug("Finished deployment of VM with hostname: " + name);
                bootCompleted = true;
            }
            if (server.getStatus().equals("ERROR")) {
                log.error("Failed to launch VM with hostname: " + name + " -> Went into ERROR");
                VimDriverException vimDriverException = new VimDriverException(server.getExtendedStatus());
                vimDriverException.setServer(server);
                throw vimDriverException;
            }
        }
        if (floatingIp != null && floatingIp.size() > 0) {
            lock.lock();
            log.debug("Assigning FloatingIPs to VM with hostname: " + name);
            log.debug("FloatingIPs are: " + floatingIp);
            int freeIps = listFreeFloatingIps(vimInstance).size();
            int ipsNeeded = floatingIp.size();
            if (freeIps < ipsNeeded) {
                log.info("Insufficient number of ips allocated to tenant, will try to allocate more ips from pool");
                log.debug("Getting the pool name of a floating ip pool");
                String pool_name = getIpPoolName(vimInstance);
                get_allocated(vimInstance, pool_name, ipsNeeded - freeIps);
            }
            if (listFreeFloatingIps(vimInstance).size() >= floatingIp.size()) {
                for (Map.Entry<String, String> fip : floatingIp.entrySet()) {
                    associateFloatingIpToNetwork(vimInstance, server, fip);
                    log.info("Assigned FloatingIPs to VM with hostname: " + name + " -> FloatingIPs: "
                            + server.getFloatingIps());
                }
            } else {
                log.error("Cannot assign FloatingIPs to VM with hostname: " + name + ". No FloatingIPs left...");
            }
            lock.unlock();
        }
        return server;
    }

    private String addKeysToUserData(String userData, Set<org.openbaton.catalogue.security.Key> keys) {
        log.debug("Going to add all keys: " + keys.size());
        userData += "\n";
        userData += "for x in `find /home/ -name authorized_keys`; do\n";
        String oldKeys = gson.toJson(keys);

        Set<org.openbaton.catalogue.security.Key> keysSet = new Gson().fromJson(oldKeys,
                new TypeToken<Set<org.openbaton.catalogue.security.Key>>() {
                }.getType());

        for (org.openbaton.catalogue.security.Key key : keysSet) {
            log.debug("Adding key: " + key.getName());
            userData += "\techo \"" + key.getPublicKey() + "\" >> $x\n";
        }
        userData += "done\n";
        return userData;
    }

    private String getNetworkIdByName(VimInstance vimInstance, String key) throws VimDriverException {
        for (Network n : this.listNetworks(vimInstance)) {
            if (n.getName().equals(key)) {
                return n.getExtId();
            }
        }
        return null;
    }

    public void rebootServer(VimInstance vimInstance, String extId, RebootType type) throws VimDriverException {
        try {
            NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NovaApi.class);
            ServerApi serverApi = novaApi.getServerApi(getZone(vimInstance));
            serverApi.reboot(extId, type);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    public void deleteServerById(VimInstance vimInstance, String extId) throws VimDriverException {
        try {
            NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NovaApi.class);
            ServerApi serverApi = novaApi.getServerApi(getZone(vimInstance));
            serverApi.delete(extId);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public void deleteServerByIdAndWait(VimInstance vimInstance, String extId) throws VimDriverException {
        boolean deleteCompleted = false;
        log.debug("Deleting VM with ExtId: " + extId);
        deleteServerById(vimInstance, extId);
        while (deleteCompleted == false) {
            log.debug("Waiting until VM with ExtId: " + extId + " is deleted...");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            try {
                getServerById(vimInstance, extId);
            } catch (NullPointerException e) {
                deleteCompleted = true;
                log.info("Deleted VM with ExtId: " + extId);
            }
        }
    }

    @Override
    public List<NFVImage> listImages(VimInstance vimInstance) throws VimDriverException {
        log.debug("Listing images for VimInstance with name: " + vimInstance.getName());
        try {
            GlanceApi glanceApi = ContextBuilder.newBuilder("openstack-glance").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(GlanceApi.class);
            ImageApi imageApi = glanceApi.getImageApi(getZone(vimInstance));
            ListImageOptions listImageOptions = new ListImageOptions();
            listImageOptions.limit(1000);
            List<NFVImage> images = new ArrayList<NFVImage>();
            for (ImageDetails jcloudsImage : imageApi.listInDetail(listImageOptions).toList()) {
                NFVImage image = new NFVImage();
                log.debug("Found image: " + jcloudsImage.getName());
                image.setName(jcloudsImage.getName());
                image.setExtId(jcloudsImage.getId());
                image.setMinRam(jcloudsImage.getMinRam());
                image.setMinDiskSpace(jcloudsImage.getMinDisk());
                image.setCreated(jcloudsImage.getCreatedAt());
                image.setUpdated(jcloudsImage.getUpdatedAt());
                image.setIsPublic(jcloudsImage.isPublic());
                image.setDiskFormat(jcloudsImage.getDiskFormat().toString().toUpperCase());
                image.setContainerFormat(jcloudsImage.getContainerFormat().toString().toUpperCase());
                images.add(image);
            }
            log.info("Listed images for VimInstance with name: " + vimInstance.getName() + " -> Images: " + images);
            return images;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public List<Server> listServer(VimInstance vimInstance) throws VimDriverException {
        log.debug("Listing all VMs on VimInstance with name: " + vimInstance.getName());
        try {
            List<Server> servers = new ArrayList<Server>();
            NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NovaApi.class);
            ServerApi serverApi = novaApi.getServerApi(getZone(vimInstance));
            String tenantId = getTenantId(vimInstance);
            for (org.jclouds.openstack.nova.v2_0.domain.Server jcloudsServer : serverApi.listInDetail().concat()) {
                if (jcloudsServer.getTenantId().equals(tenantId)) {
                    log.debug("Found jclouds VM: " + jcloudsServer);
                    Server server = new Server();
                    server.setExtId(jcloudsServer.getId());
                    server.setName(jcloudsServer.getName());
                    server.setStatus(jcloudsServer.getStatus().value());
                    server.setExtendedStatus(jcloudsServer.getExtendedStatus().toString());
                    if (jcloudsServer.getExtendedAttributes().isPresent()) {
                        server.setHostName(jcloudsServer.getExtendedAttributes().get().getHostName());
                        server.setHypervisorHostName(
                                jcloudsServer.getExtendedAttributes().get().getHypervisorHostName());
                    }
                    HashMap<String, List<String>> ipMap = new HashMap<String, List<String>>();
                    for (String key : jcloudsServer.getAddresses().keys()) {
                        List<String> ips = new ArrayList<String>();
                        for (Address address : jcloudsServer.getAddresses().get(key)) {
                            ips.add(address.getAddr());
                        }
                        ipMap.put(key, ips);
                    }
                    server.setIps(ipMap);
                    server.setFloatingIps(new HashMap<String, String>());
                    server.setCreated(jcloudsServer.getCreated());
                    server.setUpdated(jcloudsServer.getUpdated());
                    Resource image = jcloudsServer.getImage();
                    if (image != null) {
                        server.setImage(getImageById(vimInstance, image.getId()));
                    } else {
                        log.warn("The image this server is using was deleted");
                    }
                    Resource flavor = jcloudsServer.getFlavor();
                    if (flavor != null) {
                        server.setFlavor(getFlavorById(vimInstance, flavor.getId()));
                    } else {
                        log.warn("The flavor this server is using was deleted");
                    }
                    log.debug("Found VM: " + server);
                    servers.add(server);
                }
            }
            log.info("Listed all VMs on VimInstance with name: " + vimInstance.getName() + " -> VMs: " + servers);
            return servers;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    private Server getServerById(VimInstance vimInstance, String extId) throws VimDriverException {
        log.debug("Finding VM by ID: " + extId + " on VimInstance with name: " + vimInstance.getName());
        try {
            NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NovaApi.class);
            ServerApi serverApi = novaApi.getServerApi(getZone(vimInstance));
            org.jclouds.openstack.nova.v2_0.domain.Server jcloudsServer = serverApi.get(extId);
            log.debug("Found jclouds VM by ID: " + extId + " on VimInstance with name: " + vimInstance.getName()
                    + " -> VM: " + jcloudsServer);
            Server server = new Server();
            server.setExtId(jcloudsServer.getId());
            server.setName(jcloudsServer.getName());
            server.setStatus(jcloudsServer.getStatus().value());
            server.setExtendedStatus(jcloudsServer.getExtendedStatus().toString());
            HashMap<String, List<String>> ipMap = new HashMap<>();

            for (String key : jcloudsServer.getAddresses().keys()) {
                List<String> ips = new ArrayList<>();
                for (Address address : jcloudsServer.getAddresses().get(key)) {
                    ips.add(address.getAddr());
                }
                ipMap.put(key, ips);
            }

            server.setIps(ipMap);
            server.setFloatingIps(new HashMap<String, String>());
            server.setCreated(jcloudsServer.getCreated());
            server.setUpdated(jcloudsServer.getUpdated());
            Resource image = jcloudsServer.getImage();
            if (image != null) {
                server.setImage(getImageById(vimInstance, image.getId()));
            } else {
                log.warn("The image this server is using was deleted");
            }
            Resource flavor = jcloudsServer.getFlavor();
            if (flavor != null) {
                server.setFlavor(getFlavorById(vimInstance, flavor.getId()));
            } else {
                log.warn("The flavor this server is using was deleted");
            }
            log.info("Found VM by ID: " + extId + " on VimInstance with name: " + vimInstance.getName() + " -> VM: "
                    + server);
            return server;
        } catch (NullPointerException e) {
            log.debug(
                    "Not found jclouds VM by ID: " + extId + " on VimInstance with name: " + vimInstance.getName());
            throw new NullPointerException("Not found Server with ExtId: " + extId + " on VimInstance with name: "
                    + vimInstance.getName());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public NFVImage addImage(VimInstance vimInstance, NFVImage image, byte[] imageFile) throws VimDriverException {
        NFVImage addedImage = addImage(vimInstance, image.getName(), new ByteArrayInputStream(imageFile),
                image.getDiskFormat(), image.getContainerFormat(), image.getMinDiskSpace(), image.getMinRam(),
                image.isPublic());
        image.setName(addedImage.getName());
        image.setExtId(addedImage.getExtId());
        image.setCreated(addedImage.getCreated());
        image.setUpdated(addedImage.getUpdated());
        image.setMinDiskSpace(addedImage.getMinDiskSpace());
        image.setMinRam(addedImage.getMinRam());
        image.setIsPublic(addedImage.isPublic());
        image.setDiskFormat(addedImage.getDiskFormat());
        image.setContainerFormat(addedImage.getContainerFormat());
        return image;
    }

    private NFVImage addImage(VimInstance vimInstance, String name, InputStream payload, String diskFormat,
            String containerFormat, long minDisk, long minRam, boolean isPublic) throws VimDriverException {
        log.debug("Adding Image (with image file) with name: " + name + " to VimInstance with name: "
                + vimInstance.getName());
        try {
            GlanceApi glanceApi = ContextBuilder.newBuilder("openstack-glance").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(GlanceApi.class);
            ImageApi imageApi = glanceApi.getImageApi(getZone(vimInstance));
            CreateImageOptions createImageOptions = new CreateImageOptions();
            createImageOptions.minDisk(minDisk);
            createImageOptions.minRam(minRam);
            createImageOptions.isPublic(isPublic);
            createImageOptions.diskFormat(DiskFormat.valueOf(diskFormat));
            createImageOptions.containerFormat(ContainerFormat.valueOf(containerFormat));
            log.debug("Initialized jclouds Image: " + createImageOptions);
            Payload jcloudsPayload = new InputStreamPayload(payload);
            try {
                ByteArrayOutputStream bufferedPayload = new ByteArrayOutputStream();
                int read = 0;
                byte[] bytes = new byte[1024];
                while ((read = payload.read(bytes)) != -1) {
                    bufferedPayload.write(bytes, 0, read);
                }
                bufferedPayload.flush();
                jcloudsPayload = new ByteArrayPayload(bufferedPayload.toByteArray());
            } catch (IOException e) {
                log.error(e.getMessage(), e);
                throw new VimDriverException(e.getMessage());
            }
            ImageDetails imageDetails = imageApi.create(name, jcloudsPayload,
                    new CreateImageOptions[] { createImageOptions });
            log.debug(
                    "Added jclouds Image: " + imageDetails + " to VimInstance with name: " + vimInstance.getName());
            NFVImage image = new NFVImage();
            image.setName(imageDetails.getName());
            image.setExtId(imageDetails.getId());
            image.setCreated(imageDetails.getCreatedAt());
            image.setUpdated(imageDetails.getUpdatedAt());
            image.setMinDiskSpace(imageDetails.getMinDisk());
            image.setMinRam(imageDetails.getMinRam());
            image.setIsPublic(imageDetails.isPublic());
            image.setDiskFormat(imageDetails.getDiskFormat().toString().toUpperCase());
            image.setContainerFormat(imageDetails.getContainerFormat().toString().toUpperCase());
            log.info("Added Image with name: " + name + " to VimInstance with name: " + vimInstance.getName()
                    + " -> Image: " + image);
            return image;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public NFVImage addImage(VimInstance vimInstance, NFVImage image, String image_url) throws VimDriverException {
        NFVImage addedImage = addImage(vimInstance, image.getName(), image_url, image.getDiskFormat(),
                image.getContainerFormat(), image.getMinDiskSpace(), image.getMinRam(), image.isPublic());
        image.setName(addedImage.getName());
        image.setExtId(addedImage.getExtId());
        image.setCreated(addedImage.getCreated());
        image.setUpdated(addedImage.getUpdated());
        image.setMinDiskSpace(addedImage.getMinDiskSpace());
        image.setMinRam(addedImage.getMinRam());
        image.setIsPublic(addedImage.isPublic());
        image.setDiskFormat(addedImage.getDiskFormat());
        image.setContainerFormat(addedImage.getContainerFormat());
        return image;
    }

    private NFVImage addImage(VimInstance vimInstance, String name, String image_url, String diskFormat,
            String containerFromat, long minDisk, long minRam, boolean isPublic) throws VimDriverException {
        log.debug("Adding Image (with image url) with name: " + name + " to VimInstance with name: "
                + vimInstance.getName());
        try {
            GlanceApi glanceApi = ContextBuilder.newBuilder("openstack-glance").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(GlanceApi.class);
            ImageApi imageApi = glanceApi.getImageApi(getZone(vimInstance));
            CreateImageOptions createImageOptions = new CreateImageOptions();
            createImageOptions.minDisk(minDisk);
            createImageOptions.minRam(minRam);
            createImageOptions.isPublic(isPublic);
            createImageOptions.diskFormat(DiskFormat.valueOf(diskFormat));
            createImageOptions.containerFormat(ContainerFormat.valueOf(containerFromat));
            createImageOptions.copyFrom(image_url);
            log.debug("Initialized jclouds Image: " + createImageOptions);
            //Create the Image
            ImageDetails imageDetails = imageApi.reserve(name, new CreateImageOptions[] { createImageOptions });
            log.debug(
                    "Added jclouds Image: " + imageDetails + " to VimInstance with name: " + vimInstance.getName());
            NFVImage image = new NFVImage();
            image.setName(imageDetails.getName());
            image.setExtId(imageDetails.getId());
            image.setCreated(imageDetails.getCreatedAt());
            image.setUpdated(imageDetails.getUpdatedAt());
            image.setMinDiskSpace(imageDetails.getMinDisk());
            image.setMinRam(imageDetails.getMinRam());
            image.setIsPublic(imageDetails.isPublic());
            image.setDiskFormat(imageDetails.getDiskFormat().toString().toUpperCase());
            image.setContainerFormat(imageDetails.getContainerFormat().toString().toUpperCase());
            log.info("Added Image with name: " + name + " to VimInstance with name: " + vimInstance.getName()
                    + " -> Image: " + image);
            return image;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public boolean deleteImage(VimInstance vimInstance, NFVImage image) throws VimDriverException {
        log.debug("Deleting Image with name: " + image.getName() + " (ExtId: " + image.getExtId()
                + ") from VimInstance with name: " + vimInstance.getName());
        try {
            GlanceApi glanceApi = ContextBuilder.newBuilder("openstack-glance").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(GlanceApi.class);
            ImageApi imageApi = glanceApi.getImageApi(getZone(vimInstance));
            boolean isDeleted = imageApi.delete(image.getExtId());
            log.info("Deleted Image with name: " + image.getName() + " (ExtId: " + image.getExtId()
                    + ") from VimInstance with name: " + vimInstance.getName());
            return isDeleted;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public NFVImage updateImage(VimInstance vimInstance, NFVImage image) throws VimDriverException {
        NFVImage updatedImage = updateImage(vimInstance, image.getExtId(), image.getName(), image.getDiskFormat(),
                image.getContainerFormat(), image.getMinDiskSpace(), image.getMinRam(), image.isPublic());
        image.setName(updatedImage.getName());
        image.setExtId(updatedImage.getExtId());
        image.setCreated(updatedImage.getCreated());
        image.setUpdated(updatedImage.getUpdated());
        image.setMinDiskSpace(updatedImage.getMinDiskSpace());
        image.setMinRam(updatedImage.getMinRam());
        image.setIsPublic(updatedImage.isPublic());
        image.setDiskFormat(updatedImage.getDiskFormat());
        image.setContainerFormat(updatedImage.getContainerFormat());
        return image;
    }

    private NFVImage updateImage(VimInstance vimInstance, String extId, String name, String diskFormat,
            String containerFormat, long minDisk, long minRam, boolean isPublic) throws VimDriverException {
        log.debug("Updating Image with name: " + name + " (ExtId: " + extId + ") on VimInstance with name: "
                + vimInstance.getName());
        try {
            GlanceApi glanceApi = ContextBuilder.newBuilder("openstack-glance").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(GlanceApi.class);
            ImageApi imageApi = glanceApi.getImageApi(getZone(vimInstance));
            UpdateImageOptions updateImageOptions = new UpdateImageOptions();
            updateImageOptions.name(name);
            updateImageOptions.minRam(minRam);
            updateImageOptions.minDisk(minDisk);
            updateImageOptions.isPublic(isPublic);
            updateImageOptions.diskFormat(DiskFormat.valueOf(diskFormat));
            updateImageOptions.containerFormat(ContainerFormat.valueOf(containerFormat));
            ImageDetails imageDetails = imageApi.update(extId, updateImageOptions);
            NFVImage image = new NFVImage();
            image.setName(imageDetails.getName());
            image.setExtId(imageDetails.getId());
            image.setCreated(imageDetails.getCreatedAt());
            image.setUpdated(imageDetails.getUpdatedAt());
            image.setMinDiskSpace(imageDetails.getMinDisk());
            image.setMinRam(imageDetails.getMinRam());
            image.setIsPublic(imageDetails.isPublic());
            image.setDiskFormat(imageDetails.getDiskFormat().toString().toUpperCase());
            image.setContainerFormat(imageDetails.getContainerFormat().toString().toUpperCase());
            log.info("Updated Image with name: " + image.getName() + " (ExtId: " + image.getExtId()
                    + ") on VimInstance with name: " + vimInstance.getName() + " -> updated Image: " + image);
            return image;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public NFVImage copyImage(VimInstance vimInstance, NFVImage image, byte[] imageFile) throws VimDriverException {
        NFVImage copiedImage = copyImage(vimInstance, image.getName(), new ByteArrayInputStream(imageFile),
                image.getDiskFormat(), image.getContainerFormat(), image.getMinDiskSpace(), image.getMinRam(),
                image.isPublic());
        image.setName(copiedImage.getName());
        image.setExtId(copiedImage.getExtId());
        image.setCreated(copiedImage.getCreated());
        image.setUpdated(copiedImage.getUpdated());
        image.setMinDiskSpace(copiedImage.getMinDiskSpace());
        image.setMinRam(copiedImage.getMinRam());
        image.setIsPublic(copiedImage.isPublic());
        image.setDiskFormat(copiedImage.getDiskFormat());
        image.setContainerFormat(copiedImage.getContainerFormat());
        return image;
    }

    private NFVImage copyImage(VimInstance vimInstance, String name, InputStream inputStream, String diskFormat,
            String containerFormat, long minDisk, long minRam, boolean isPublic) throws VimDriverException {
        try {
            GlanceApi glanceApi = ContextBuilder.newBuilder("openstack-glance").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(GlanceApi.class);
            ImageApi imageApi = glanceApi.getImageApi(getZone(vimInstance));
            NFVImage image = addImage(vimInstance, name, inputStream, diskFormat, containerFormat, minDisk, minRam,
                    isPublic);
            return image;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    private NFVImage getImageById(VimInstance vimInstance, String extId) throws VimDriverException {
        log.debug("Finding Image by ExtId: " + extId);
        try {
            NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NovaApi.class);
            org.jclouds.openstack.nova.v2_0.features.ImageApi imageApi = novaApi.getImageApi(getZone(vimInstance));
            org.jclouds.openstack.nova.v2_0.domain.Image jcloudsImage = imageApi.get(extId);
            NFVImage image = new NFVImage();
            image.setExtId(jcloudsImage.getId());
            image.setName(jcloudsImage.getName());
            image.setCreated(jcloudsImage.getCreated());
            image.setUpdated(jcloudsImage.getUpdated());
            image.setMinDiskSpace(jcloudsImage.getMinDisk());
            image.setMinRam(jcloudsImage.getMinRam());
            image.setIsPublic(false);
            image.setContainerFormat("not provided");
            image.setDiskFormat("not provided");
            log.info("Found Image by ExtId: " + extId + " -> Image: " + image);
            return image;
        } catch (NullPointerException e) {
            log.warn(e.getMessage(), new NullPointerException("Image with extId: " + extId + " not found."));
            NFVImage image = new NFVImage();
            image.setExtId(extId);
            return image;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public DeploymentFlavour addFlavor(VimInstance vimInstance, DeploymentFlavour flavor)
            throws VimDriverException {
        DeploymentFlavour addedFlavor = addFlavor(vimInstance, flavor.getFlavour_key(), flavor.getVcpus(),
                flavor.getRam(), flavor.getDisk());
        flavor.setExtId(addedFlavor.getExtId());
        flavor.setFlavour_key(addedFlavor.getFlavour_key());
        flavor.setVcpus(addedFlavor.getVcpus());
        flavor.setRam(addedFlavor.getRam());
        flavor.setDisk(addedFlavor.getVcpus());
        return flavor;
    }

    private DeploymentFlavour addFlavor(VimInstance vimInstance, String name, int vcpus, int ram, int disk)
            throws VimDriverException {
        log.debug("Adding Flavor with name: " + name + " to VimInstance with name: " + vimInstance.getName());
        try {
            NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NovaApi.class);
            FlavorApi flavorApi = novaApi.getFlavorApi(getZone(vimInstance));
            UUID id = java.util.UUID.randomUUID();
            org.jclouds.openstack.nova.v2_0.domain.Flavor newFlavor = org.jclouds.openstack.nova.v2_0.domain.Flavor
                    .builder().id(id.toString()).name(name).disk(disk).ram(ram).vcpus(vcpus).build();
            org.jclouds.openstack.nova.v2_0.domain.Flavor jcloudsFlavor = flavorApi.create(newFlavor);
            DeploymentFlavour flavor = new DeploymentFlavour();
            flavor.setExtId(jcloudsFlavor.getId());
            flavor.setFlavour_key(jcloudsFlavor.getName());
            flavor.setVcpus(jcloudsFlavor.getVcpus());
            flavor.setRam(jcloudsFlavor.getRam());
            flavor.setDisk(jcloudsFlavor.getVcpus());
            log.info("Added Flavor with name: " + name + " to VimInstance with name: " + vimInstance.getName()
                    + " -> Flavor: " + flavor);
            return flavor;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public DeploymentFlavour updateFlavor(VimInstance vimInstance, DeploymentFlavour flavor)
            throws VimDriverException {
        DeploymentFlavour updatedFlavor = updateFlavor(vimInstance, flavor.getExtId(), flavor.getFlavour_key(),
                flavor.getVcpus(), flavor.getRam(), flavor.getDisk());
        flavor.setFlavour_key(updatedFlavor.getFlavour_key());
        flavor.setExtId(updatedFlavor.getExtId());
        flavor.setRam(updatedFlavor.getRam());
        flavor.setDisk(updatedFlavor.getDisk());
        flavor.setVcpus(updatedFlavor.getVcpus());
        return flavor;
    }

    private DeploymentFlavour updateFlavor(VimInstance vimInstance, String extId, String name, int vcpus, int ram,
            int disk) throws VimDriverException {
        log.debug("Updating Flavor with name: " + name + " on VimInstance with name: " + vimInstance.getName());
        try {
            NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NovaApi.class);
            FlavorApi flavorApi = novaApi.getFlavorApi(getZone(vimInstance));
            boolean isDeleted = deleteFlavor(vimInstance, extId);
            if (isDeleted) {
                org.jclouds.openstack.nova.v2_0.domain.Flavor newFlavor = org.jclouds.openstack.nova.v2_0.domain.Flavor
                        .builder().id(extId).name(name).disk(disk).ram(ram).vcpus(vcpus).build();
                org.jclouds.openstack.nova.v2_0.domain.Flavor jcloudsFlavor = flavorApi.create(newFlavor);
                DeploymentFlavour updatedFlavor = new DeploymentFlavour();
                updatedFlavor.setExtId(jcloudsFlavor.getId());
                updatedFlavor.setFlavour_key(jcloudsFlavor.getName());
                updatedFlavor.setVcpus(jcloudsFlavor.getVcpus());
                updatedFlavor.setRam(jcloudsFlavor.getRam());
                updatedFlavor.setDisk(jcloudsFlavor.getVcpus());
                log.info("Updated Flavor with name: " + name + " on VimInstance with name: " + vimInstance.getName()
                        + " -> Flavor: " + updatedFlavor);
                return updatedFlavor;
            } else {
                throw new VimDriverException("Image with extId: " + extId
                        + " not updated successfully. Not able to delete it and create a new one.");
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public boolean deleteFlavor(VimInstance vimInstance, String extId) throws VimDriverException {
        log.debug("Deleting Flavor with ExtId: " + extId + " from VimInstance with name: " + vimInstance.getName());
        try {
            NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NovaApi.class);
            FlavorApi flavorApi = novaApi.getFlavorApi(getZone(vimInstance));
            flavorApi.delete(extId);
            boolean isDeleted;
            try {
                DeploymentFlavour flavour = getFlavorById(vimInstance, extId);
                if (flavour.getFlavour_key() == null) {
                    throw new NullPointerException();
                }
                isDeleted = false;
                log.warn("Not deleted Flavor with ExtId: " + extId + " from VimInstance with name: "
                        + vimInstance.getName());
            } catch (NullPointerException e) {
                isDeleted = true;
                log.info("Deleted Flavor with ExtId: " + extId + " from VimInstance with name: "
                        + vimInstance.getName());
            }
            return isDeleted;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    private DeploymentFlavour getFlavorById(VimInstance vimInstance, String extId) throws VimDriverException {
        log.debug("Finding Flavor with ExtId: " + extId + " on VimInstance with name: " + vimInstance.getName());
        try {
            NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NovaApi.class);
            FlavorApi flavorApi = novaApi.getFlavorApi(getZone(vimInstance));
            org.jclouds.openstack.nova.v2_0.domain.Flavor jcloudsFlavor = flavorApi.get(extId);
            DeploymentFlavour flavor = new DeploymentFlavour();
            flavor.setFlavour_key(jcloudsFlavor.getName());
            flavor.setExtId(jcloudsFlavor.getId());
            flavor.setRam(jcloudsFlavor.getRam());
            flavor.setDisk(jcloudsFlavor.getDisk());
            flavor.setVcpus(jcloudsFlavor.getVcpus());
            log.info("Found Flavor with ExtId: " + extId + " on VimInstance with name: " + vimInstance.getName());
            return flavor;
        } catch (NullPointerException e) {
            log.warn(e.getMessage(), new NullPointerException("Flavor with extId: " + extId
                    + " not found on VimInstance with name: " + vimInstance.getName()));
            DeploymentFlavour flavor = new DeploymentFlavour();
            flavor.setExtId(extId);
            return flavor;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public List<DeploymentFlavour> listFlavors(VimInstance vimInstance) throws VimDriverException {
        log.debug("Listing Flavours on VimInstance with name: " + vimInstance.getName());
        try {
            NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NovaApi.class);
            FlavorApi flavorApi = novaApi.getFlavorApi(getZone(vimInstance));
            List<DeploymentFlavour> flavors = new ArrayList<DeploymentFlavour>();
            for (org.jclouds.openstack.nova.v2_0.domain.Flavor jcloudsFlavor : flavorApi.listInDetail().concat()) {
                DeploymentFlavour flavor = new DeploymentFlavour();
                log.debug("Found jclouds Flavour: " + jcloudsFlavor);
                flavor.setExtId(jcloudsFlavor.getId());
                flavor.setFlavour_key(jcloudsFlavor.getName());
                flavor.setRam(jcloudsFlavor.getRam());
                flavor.setDisk(jcloudsFlavor.getDisk());
                flavor.setVcpus(jcloudsFlavor.getVcpus());
                log.debug("Found Flavour: " + flavor);
                flavors.add(flavor);
            }
            log.info("Listed Flavours on VimInstance with name: " + vimInstance.getName() + " -> Flavours: "
                    + flavors);
            return flavors;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public Network createNetwork(VimInstance vimInstance, Network network) throws VimDriverException {
        Network createdNetwork = createNetwork(vimInstance, network.getName(), network.getExternal(),
                network.getShared());
        network.setName(createdNetwork.getName());
        network.setExtId(createdNetwork.getExtId());
        network.setExternal(createdNetwork.getExternal());
        network.setShared(createdNetwork.getShared());
        return network;
    }

    private Network createNetwork(VimInstance vimInstance, String name, boolean external, boolean shared)
            throws VimDriverException {
        log.debug("Creating Network with name: " + name + " on VimInstance with name: " + vimInstance.getName());
        org.jclouds.openstack.neutron.v2.domain.Network jcloudsNetwork;
        try {
            NeutronApi neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NeutronApi.class);
            NetworkApi networkApi = neutronApi.getNetworkApi(getZone(vimInstance));
            //CreateNetwork createNetwork = CreateNetwork.createBuilder(name).networkType(NetworkType.fromValue
            // (networkType)).external(external).shared(shared).segmentationId(segmentationId).physicalNetworkName
            // (physicalNetworkName).build();
            CreateNetwork createNetwork = CreateNetwork.createBuilder(name).external(external).shared(shared)
                    .build();
            log.debug("Initialized jclouds Network: " + createNetwork);

            jcloudsNetwork = networkApi.create(createNetwork);
        } catch (Exception e) {
            log.warn("Could not create a network");
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
        log.debug("Created jclouds Network: " + jcloudsNetwork);
        Network network = new Network();
        network.setName(jcloudsNetwork.getName());
        network.setExtId(jcloudsNetwork.getId());
        network.setExternal(jcloudsNetwork.getExternal());
        network.setShared(jcloudsNetwork.getShared());
        network.setSubnets(new HashSet<Subnet>());
        for (String subnetId : jcloudsNetwork.getSubnets()) {
            try {
                network.getSubnets().add(getSubnetById(vimInstance, subnetId));
            } catch (Exception e) {
                log.warn("Not able to find subnets. Not able to find subnet with id" + subnetId);
            }
        }
        log.info("Created Network with name: " + name + " on VimInstance with name: " + vimInstance.getName()
                + " -> Network: " + network);
        return network;

        //return null;
    }

    @Override
    public Network updateNetwork(VimInstance vimInstance, Network network) throws VimDriverException {
        Network updatedNetwork = updateNetwork(vimInstance, network.getExtId(), network.getName(),
                network.getExternal(), network.getShared());
        network.setName(updatedNetwork.getName());
        network.setExtId(updatedNetwork.getExtId());
        network.setExternal(updatedNetwork.getExternal());
        network.setShared(updatedNetwork.getShared());
        return network;
    }

    private Network updateNetwork(VimInstance vimInstance, String extId, String name, boolean external,
            boolean shared) throws VimDriverException {
        log.debug("Updating Network with name: " + name + " on VimInstance with name: " + vimInstance.getName());
        try {
            NeutronApi neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NeutronApi.class);
            NetworkApi networkApi = neutronApi.getNetworkApi(getZone(vimInstance));
            //Plugin does not support updating provider attributes. -> NetworkType, SegmentationId, physicalNetworkName
            UpdateNetwork updateNetwork = UpdateNetwork.updateBuilder().name(name).build();
            org.jclouds.openstack.neutron.v2.domain.Network jcloudsNetwork = networkApi.update(extId,
                    updateNetwork);
            Network network = new Network();
            network.setName(jcloudsNetwork.getName());
            network.setExtId(jcloudsNetwork.getId());
            network.setExternal(jcloudsNetwork.getExternal());
            network.setShared(jcloudsNetwork.getShared());
            network.setSubnets(new HashSet<Subnet>());
            for (String subnetId : jcloudsNetwork.getSubnets()) {
                network.getSubnets().add(getSubnetById(vimInstance, subnetId));
            }
            log.debug("Updated Network with name: " + name + " on VimInstance with name: " + vimInstance.getName()
                    + " -> Network: " + network);
            return network;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public boolean deleteNetwork(VimInstance vimInstance, String extId) throws VimDriverException {
        log.debug(
                "Deleting Network with ExtId: " + extId + " from VimInstance with name: " + vimInstance.getName());
        try {
            NeutronApi neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NeutronApi.class);
            NetworkApi networkApi = neutronApi.getNetworkApi(getZone(vimInstance));
            boolean isDeleted = networkApi.delete(extId);
            if (isDeleted == true) {
                log.debug("Deleted Network with ExtId: " + extId + " from VimInstance with name: "
                        + vimInstance.getName());
            } else {
                log.debug("Not deleted Network with ExtId: " + extId + " from VimInstance with name: "
                        + vimInstance.getName());
            }
            return isDeleted;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public Network getNetworkById(VimInstance vimInstance, String extId) throws VimDriverException {
        log.debug("Finding Network with ExtId: " + extId + " on VimInstance with name: " + vimInstance.getName());
        try {
            NeutronApi neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NeutronApi.class);
            NetworkApi networkApi = neutronApi.getNetworkApi(getZone(vimInstance));
            org.jclouds.openstack.neutron.v2.domain.Network jcloudsNetwork = networkApi.get(extId);
            Network network = new Network();
            network.setName(jcloudsNetwork.getName());
            network.setExtId(jcloudsNetwork.getId());
            network.setExternal(jcloudsNetwork.getExternal());
            network.setShared(jcloudsNetwork.getShared());
            network.setSubnets(new HashSet<Subnet>());
            for (String subnetId : jcloudsNetwork.getSubnets()) {
                network.getSubnets().add(getSubnetById(vimInstance, subnetId));
            }
            log.info("Found Network with ExtId: " + extId + " on VimInstance with name: " + vimInstance.getName()
                    + " -> " + network);
            return network;
        } catch (NullPointerException e) {
            log.error("Not found Network with ExtId: " + extId + " on VimInstance with name: "
                    + vimInstance.getName(), e);
            throw new NullPointerException("Not found Network with ExtId: " + extId + " on VimInstance with name: "
                    + vimInstance.getName());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public List<String> getSubnetsExtIds(VimInstance vimInstance, String extId) throws VimDriverException {
        log.debug("Listing all external SubnetIDs for Network with ExtId: " + extId
                + " from VimInstance with name: " + vimInstance.getName());
        try {
            NeutronApi neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NeutronApi.class);
            NetworkApi networkApi = neutronApi.getNetworkApi(getZone(vimInstance));
            List<String> subnets = new ArrayList<String>();
            org.jclouds.openstack.neutron.v2.domain.Network jcloudsNetwork = networkApi.get(extId);
            subnets = jcloudsNetwork.getSubnets().asList();
            log.info("Listed all external SubnetIDs for Network with ExtId: " + extId
                    + " from VimInstance with name: " + vimInstance.getName() + " -> external Subnet IDs: "
                    + subnets);
            return subnets;
        } catch (NullPointerException e) {
            log.error("Not found Network with ExtId: " + extId + " on VimInstance with name: "
                    + vimInstance.getName(), e);
            throw new NullPointerException("Not found Network with ExtId: " + extId + " on VimInstance with name: "
                    + vimInstance.getName());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public List<Network> listNetworks(VimInstance vimInstance) throws VimDriverException {
        log.debug("Listing all Networks of VimInstance with name: " + vimInstance.getName());
        try {
            NeutronApi neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NeutronApi.class);
            List<Network> networks = new ArrayList<Network>();
            String tenantId = getTenantId(vimInstance);
            for (org.jclouds.openstack.neutron.v2.domain.Network jcloudsNetwork : neutronApi
                    .getNetworkApi(getZone(vimInstance)).list().concat()) {
                if (jcloudsNetwork.getTenantId().equals(tenantId) || jcloudsNetwork.getShared()) {
                    log.debug("Found jclouds Network: " + jcloudsNetwork);
                    Network network = new Network();
                    network.setName(jcloudsNetwork.getName());
                    network.setExtId(jcloudsNetwork.getId());
                    network.setExternal(jcloudsNetwork.getExternal());
                    network.setShared(jcloudsNetwork.getShared());
                    network.setSubnets(new HashSet<Subnet>());
                    for (String subnetId : jcloudsNetwork.getSubnets()) {
                        network.getSubnets().add(getSubnetById(vimInstance, subnetId));
                    }
                    log.debug("Found Network: " + network);
                    networks.add(network);
                }
            }
            log.info("Listed all Networks of VimInstance with name: " + vimInstance.getName() + " -> Networks: "
                    + networks);
            return networks;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    private Subnet getSubnetById(VimInstance vimInstance, String extId) throws VimDriverException {
        log.debug("Getting Subnet with extId: " + extId + " from VimInstance with name: " + vimInstance.getName());
        try {
            NeutronApi neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NeutronApi.class);
            SubnetApi subnetApi = neutronApi.getSubnetApi(getZone(vimInstance));
            org.jclouds.openstack.neutron.v2.domain.Subnet jcloudsSubnet = subnetApi.get(extId);
            log.debug("Got jclouds Subnet: " + jcloudsSubnet);
            Subnet subnet = new Subnet();
            subnet.setExtId(jcloudsSubnet.getId());
            subnet.setName(jcloudsSubnet.getName());
            subnet.setCidr(jcloudsSubnet.getCidr());
            subnet.setGatewayIp(jcloudsSubnet.getGatewayIp());
            subnet.setNetworkId(jcloudsSubnet.getNetworkId());
            log.info("Found Subnet with extId: " + extId + " on VimInstance with name: " + vimInstance.getName()
                    + " -> Subnet: " + subnet);
            return subnet;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public Subnet createSubnet(VimInstance vimInstance, Network network, Subnet subnet) throws VimDriverException {
        Subnet createdSubnet = createSubnet(vimInstance, network, subnet.getName(), subnet.getCidr());
        subnet.setExtId(createdSubnet.getExtId());
        subnet.setName(createdSubnet.getName());
        subnet.setCidr(createdSubnet.getCidr());
        subnet.setGatewayIp(createdSubnet.getGatewayIp());
        return subnet;
    }

    private Subnet createSubnet(VimInstance vimInstance, Network network, String name, String cidr)
            throws VimDriverException {
        log.debug("Creating Subnet with name: " + name + " on Network with name: + " + network.getName()
                + " on VimInstance with name: " + vimInstance.getName());
        try {
            NeutronApi neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NeutronApi.class);
            SubnetApi subnetApi = neutronApi.getSubnetApi(getZone(vimInstance));
            CreateSubnet createSubnet = CreateSubnet.createBuilder(network.getExtId(), cidr).name(name)
                    .dnsNameServers(ImmutableSet.<String>of(properties.getProperty("dns-nameserver"))).ipVersion(4)
                    .build();
            log.debug("Initialized jclouds Network: " + createSubnet);
            org.jclouds.openstack.neutron.v2.domain.Subnet jcloudsSubnet = subnetApi.create(createSubnet);
            log.debug("Created jclouds Network: " + jcloudsSubnet);
            Subnet subnet = new Subnet();
            subnet.setExtId(jcloudsSubnet.getId());
            subnet.setName(jcloudsSubnet.getName());
            subnet.setCidr(jcloudsSubnet.getCidr());
            subnet.setGatewayIp(jcloudsSubnet.getGatewayIp());
            String routerId = getRouter(vimInstance);
            if (routerId == null) {
                log.debug("Not found Router");
                routerId = createRouter(vimInstance);
            }
            if (routerId != null) {
                String portId = createPort(vimInstance, network, subnet);
                attachPort(vimInstance, routerId, portId);
            }
            log.info("Created Subnet with name: " + name + " on Network with name: + " + network.getName()
                    + " on VimInstance with name: " + vimInstance.getName() + " -> Subnet: " + subnet);
            return subnet;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public Subnet updateSubnet(VimInstance vimInstance, Network network, Subnet subnet) throws VimDriverException {
        Subnet updatedSubnet = updateSubnet(vimInstance, network, subnet.getExtId(), subnet.getName());
        subnet.setExtId(updatedSubnet.getExtId());
        subnet.setName(updatedSubnet.getName());
        subnet.setCidr(updatedSubnet.getCidr());
        subnet.setGatewayIp(updatedSubnet.getGatewayIp());
        return subnet;
    }

    private Subnet updateSubnet(VimInstance vimInstance, Network network, String subnetExtId, String name)
            throws VimDriverException {
        log.debug("Updating Subnet with ExtId: " + subnetExtId + " on Network with name: + " + network.getName()
                + " on VimInstance with name: " + vimInstance.getName());
        try {
            NeutronApi neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NeutronApi.class);
            SubnetApi subnetApi = neutronApi.getSubnetApi(getZone(vimInstance));
            UpdateSubnet updateSubnet = UpdateSubnet.updateBuilder().name(name).build();
            org.jclouds.openstack.neutron.v2.domain.Subnet jcloudsSubnet = subnetApi.update(subnetExtId,
                    updateSubnet);
            Subnet subnet = new Subnet();
            subnet.setExtId(jcloudsSubnet.getId());
            subnet.setName(jcloudsSubnet.getName());
            subnet.setCidr(jcloudsSubnet.getCidr());
            subnet.setGatewayIp(jcloudsSubnet.getGatewayIp());
            log.debug("Updated Subnet with ExtId: " + subnetExtId + " on Network with name: + " + network.getName()
                    + " on VimInstance with name: " + vimInstance.getName() + " -> Subnet: " + subnet);
            return subnet;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    private String getRouter(VimInstance vimInstance) throws VimDriverException {
        log.debug("Finding a Router that is connected with external Network on VimInstance with name: "
                + vimInstance.getName());
        try {
            NeutronApi neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NeutronApi.class);

            RouterApi routerApi = neutronApi.getRouterApi(getZone(vimInstance)).get();
            PagedIterable routerList = routerApi.list();
            String tenantId = getTenantId(vimInstance);
            if (routerList.iterator().hasNext()) {
                for (Router router : (FluentIterable<Router>) routerList.concat()) {
                    if (router.getTenantId().equals(tenantId)) {
                        ExternalGatewayInfo externalGatewayInfo = router.getExternalGatewayInfo();
                        if (externalGatewayInfo != null) {
                            String networkId = externalGatewayInfo.getNetworkId();
                            if (getNetworkById(vimInstance, networkId).getExternal()) {
                                log.info(
                                        "Found a Router that is connected with external Network on VimInstance with name: "
                                                + vimInstance.getName());
                                return router.getId();
                            }
                        }
                    }
                }
            }
            log.warn("Not found any Router that is connected with external Network on VimInstance with name: "
                    + vimInstance.getName());
            return null;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            //      throw new VimDriverException(e.getMessage());
            return null;
        }
    }

    private String createRouter(VimInstance vimInstance) throws VimDriverException {
        log.debug("Creating a Router that is connected with external Network on VimInstance with name: "
                + vimInstance.getName());
        try {
            NeutronApi neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NeutronApi.class);
            RouterApi routerApi = neutronApi.getRouterApi(getZone(vimInstance)).get();
            //Find external network
            String externalNetId = null;
            log.debug("Finding an external Network where we can connect a new Router to on VimInstance with name: "
                    + vimInstance.getName());
            for (Network network : listNetworks(vimInstance)) {
                if (network.getExternal()) {
                    log.debug(
                            "Found an external Network where we can connect a new Router to on VimInstance with name: "
                                    + vimInstance.getName() + " -> Network: " + network);
                    externalNetId = network.getExtId();
                }
            }
            if (externalNetId == null) {
                log.warn(
                        "Not found any external Network where we can connect a new Router to on VimInstance with name: "
                                + vimInstance.getName());
                return null;
            }
            ExternalGatewayInfo externalGatewayInfo = ExternalGatewayInfo.builder().networkId(externalNetId)
                    .build();
            Router.CreateRouter options = Router.CreateRouter.createBuilder()
                    .name(vimInstance.getTenant() + "_" + (int) (Math.random() * 1000) + "_router")
                    .adminStateUp(true).externalGatewayInfo(externalGatewayInfo).build();
            Router router = routerApi.create(options);
            log.info("Created a Router that is connected with external Network on VimInstance with name: "
                    + vimInstance.getName());
            return router.getId();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            //      throw new VimDriverException(e.getMessage());
            return null;
        }
    }

    private String attachPort(VimInstance vimInstance, String routerId, String portId) throws VimDriverException {
        log.debug("Attaching Port with ExtId: " + portId + " to Router with ExtId: " + routerId
                + " on VimInstnace with name: " + vimInstance);
        try {
            NeutronApi neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NeutronApi.class);
            RouterApi routerApi = neutronApi.getRouterApi(getZone(vimInstance)).get();
            RouterInterface routerInterface = routerApi.addInterfaceForPort(routerId, portId);
            log.info("Attached Port with ExtId: " + portId + " to Router with ExtId: " + routerId
                    + " on VimInstnace with name: " + vimInstance);
            return routerInterface.getSubnetId();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    private String createPort(VimInstance vimInstance, Network network, Subnet subnet) throws VimDriverException {
        log.debug("Creating a Port for network with name: " + network.getName() + " and Subnet with name: "
                + subnet.getName() + " on VimInstance with name: " + vimInstance.getName());
        try {
            NeutronApi neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NeutronApi.class);
            PortApi portApi = neutronApi.getPortApi(getZone(vimInstance));
            Port.CreatePort createPort = Port.createBuilder(network.getExtId())
                    .name("Port_" + network.getName() + "_" + (int) (Math.random() * 1000))
                    .fixedIps(ImmutableSet.of(IP.builder().ipAddress(subnet.getGatewayIp()).build())).build();
            Port port = portApi.create(createPort);
            log.info("Created a Port for network with name: " + network.getName() + " and Subnet with name: "
                    + subnet.getName() + " on VimInstance with name: " + vimInstance.getName() + " -> Port: "
                    + port);
            return port.getId();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public boolean deleteSubnet(VimInstance vimInstance, String extId) throws VimDriverException {
        log.debug("Deleting Subnet with ExtId: " + extId + " from VimInstance with name: " + vimInstance.getName());
        try {
            NeutronApi neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NeutronApi.class);
            SubnetApi subnetApi = neutronApi.getSubnetApi(getZone(vimInstance));
            boolean isDeleted = subnetApi.delete(extId);
            if (isDeleted == true) {
                log.info("Deleted Subnet with ExtId: " + extId + " from VimInstance with name: "
                        + vimInstance.getName());
            } else {
                log.warn("Not deleted Subnet with ExtId: " + extId + " from VimInstance with name: "
                        + vimInstance.getName());
            }
            return isDeleted;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    private List<String> listFreeFloatingIps(VimInstance vimInstance) throws VimDriverException {
        log.debug("Listing all free FloatingIPs of VimInstance with name: " + vimInstance.getName());
        String tenantId = getTenantId(vimInstance);
        try {
            NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NovaApi.class);
            NeutronApi neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NeutronApi.class);

            //      if (novaApi.getFloatingIPApi(getZone(vimInstance)).isPresent()){
            boolean floatingIpApiNotPresent = false;
            Optional<FloatingIPApi> neutronApiFloatingIPApi = null;
            try {
                neutronApiFloatingIPApi = neutronApi.getFloatingIPApi(getZone(vimInstance));
            } catch (Exception e) {
                floatingIpApiNotPresent = true;
            }

            if (!floatingIpApiNotPresent && neutronApiFloatingIPApi.isPresent()) {
                FloatingIPApi floatingIPApi = neutronApiFloatingIPApi.get();

                //        org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi floatingIPApi =
                //            novaApi.getFloatingIPApi(getZone(vimInstance)).get();
                List<String> floatingIPs = new LinkedList<String>();

                for (FloatingIP floatingIP : floatingIPApi.list(new PaginationOptions())) {
                    if (floatingIP.getTenantId().equals(tenantId) && floatingIP.getFixedIpAddress() == null) {
                        floatingIPs.add(floatingIP.getFloatingIpAddress() /*getFloatingIpAddress()*/);
                    }
                }
                log.info("Listed all free FloatingIPs of VimInstance with name: " + vimInstance.getName()
                        + " -> free FloatingIPs: " + floatingIPs);
                return floatingIPs;
            } else {
                /*
                REQ: curl -i http://192.168.45.101:9696/v2.0/floatingips.json -X GET -H "X-Auth-Token: ..." -H
                "Content-Type: application/json" -H "Accept: application/json" -H "User-Agent: python-neutronclient"
                 */

                URI endpoint = null;
                ContextBuilder contextBuilder = ContextBuilder.newBuilder("openstack-nova")
                        .credentials(vimInstance.getUsername(), vimInstance.getPassword())
                        .endpoint(vimInstance.getAuthUrl());
                ComputeServiceContext context = contextBuilder.buildView(ComputeServiceContext.class);
                Function<Credentials, Access> auth = context.utils().injector()
                        .getInstance(Key.get(new TypeLiteral<Function<Credentials, Access>>() {
                        }));

                Access access = auth.apply(new Credentials.Builder<>()
                        .identity(vimInstance.getTenant() + ":" + vimInstance.getUsername())
                        .credential(vimInstance.getPassword()).build());

                log.debug("listing FloatingIPs: finding endpoint");
                for (org.jclouds.openstack.keystone.v2_0.domain.Service service : access) {
                    if (service.getName().equals("neutron")) {
                        for (Endpoint end : service) {
                            endpoint = end.getPublicURL();
                            break;
                        }
                        break;
                    }
                }

                HttpURLConnection connection = null;
                URL url = new URL(endpoint + "/v2.0/floatingips.json");
                connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");
                connection.setDoOutput(true);
                connection.setRequestProperty("Accept", "application/json");
                connection.setRequestProperty("Content-Type", "application/json");
                connection.setRequestProperty("User-Agent", "python-neutronclient");
                connection.setRequestProperty("X-Auth-Token", access.getToken().getId());

                InputStream is = connection.getInputStream();
                BufferedReader rd = new BufferedReader(new InputStreamReader(is));
                StringBuilder response = new StringBuilder(); // or StringBuffer if not Java 5+
                String line;
                while ((line = rd.readLine()) != null) {
                    response.append(line);
                    response.append('\r');
                }
                rd.close();
                //Parse json to object
                log.debug("List of FloatingIPs: Response of final request is: " + response.toString());

                JsonObject res = new GsonBuilder().setPrettyPrinting().create().fromJson(response.toString(),
                        JsonObject.class);

                log.debug("JsonObject is: " + res);

                List<String> result = new ArrayList<>();
                if (res.has("floatingips")) {
                    for (JsonElement element : res.get("floatingips").getAsJsonArray()) {
                        log.debug("FloatingIp is: " + element.getAsJsonObject());
                        JsonElement fixed_ip_address = element.getAsJsonObject().get("fixed_ip_address");
                        JsonElement tenant_id = element.getAsJsonObject().get("tenant_id");
                        if (!fixed_ip_address.isJsonNull() || !tenant_id.getAsString().equals(tenantId)) {
                            //              log.debug("FixedIpAddress is: " + fixed_ip_address);
                            continue;
                        }

                        String floating_ip_address = element.getAsJsonObject().get("floating_ip_address")
                                .getAsString();
                        log.debug("found ip: " + floating_ip_address);
                        result.add(floating_ip_address);
                    }
                } else {
                    log.warn("Was not possible through Openstack ReST api to retrieve all the FloatingIP");
                }
                log.info("Free Floating ips are: " + result);
                return result;
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    private void associateFloatingIp(VimInstance vimInstance, Server server, String floatingIp)
            throws VimDriverException {
        log.debug("Associating FloatingIP: " + floatingIp + " to VM with hostname: " + server.getName()
                + " on VimInstance with name: " + vimInstance.getName());
        try {
            NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NovaApi.class);
            org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi floatingIPApi = novaApi
                    .getFloatingIPApi(getZone(vimInstance)).get();
            floatingIPApi.addToServer(floatingIp, server.getExtId());
            server.setFloatingIps(new HashMap<String, String>());
            server.getFloatingIps().put("netname", floatingIp);
            log.info("Associated FloatingIP: " + floatingIp + " to VM with hostname: " + server.getName()
                    + " on VimInstance with name: " + vimInstance.getName());
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    public String getTenantId(VimInstance vimInstance) throws VimDriverException {
        log.debug("Finding TenantID for Tenant with name: " + vimInstance.getTenant()
                + " on VimInstance with name: " + vimInstance.getName());
        try {
            ContextBuilder contextBuilder = ContextBuilder.newBuilder("openstack-nova")
                    .credentials(vimInstance.getUsername(), vimInstance.getPassword())
                    .endpoint(vimInstance.getAuthUrl());
            ComputeServiceContext context = contextBuilder.buildView(ComputeServiceContext.class);
            Function<Credentials, Access> auth = context.utils().injector()
                    .getInstance(Key.get(new TypeLiteral<Function<Credentials, Access>>() {
                    }));
            //Get Access and all information
            Access access = auth.apply(new Credentials.Builder<Credentials>()
                    .identity(vimInstance.getTenant() + ":" + vimInstance.getUsername())
                    .credential(vimInstance.getPassword()).build());
            //Get Tenant ID of user
            String tenant_id = access.getToken().getTenant().get().getId();
            log.info("Found TenantID for Tenant with name: " + vimInstance.getTenant()
                    + " on VimInstance with name: " + vimInstance.getName() + " -> TenantID: " + tenant_id);
            return tenant_id;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        }
    }

    @Override
    public Quota getQuota(VimInstance vimInstance) throws VimDriverException {
        log.debug("Finding Quota for Tenant with name: " + vimInstance.getTenant() + " on VimInstance with name: "
                + vimInstance.getName());
        HttpURLConnection connection = null;
        try {
            Quota quota = new Quota();
            ContextBuilder contextBuilder = ContextBuilder.newBuilder("openstack-nova")
                    .credentials(vimInstance.getUsername(), vimInstance.getPassword())
                    .endpoint(vimInstance.getAuthUrl());
            ComputeServiceContext context = contextBuilder.buildView(ComputeServiceContext.class);
            Function<Credentials, Access> auth = context.utils().injector()
                    .getInstance(Key.get(new TypeLiteral<Function<Credentials, Access>>() {
                    }));
            //Get Access and all information
            Access access = auth.apply(new Credentials.Builder<Credentials>()
                    .identity(vimInstance.getTenant() + ":" + vimInstance.getUsername())
                    .credential(vimInstance.getPassword()).build());
            //Get Tenant ID of user
            String tenant_id = access.getToken().getTenant().get().getId();
            //Get nova endpoint
            URI endpoint = null;
            for (org.jclouds.openstack.keystone.v2_0.domain.Service service : access) {
                if (service.getName().equals("nova")) {
                    for (Endpoint end : service) {
                        endpoint = end.getPublicURL();
                        break;
                    }
                    break;
                }
            }

            //Prepare quota request
            URL url = new URL(endpoint + "/os-quota-sets/" + tenant_id);
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Accept", "application/json");
            connection.setRequestProperty("X-Auth-Token", access.getToken().getId());
            //Get Response
            InputStream is = connection.getInputStream();
            BufferedReader rd = new BufferedReader(new InputStreamReader(is));
            StringBuilder response = new StringBuilder(); // or StringBuffer if not Java 5+
            String line;
            while ((line = rd.readLine()) != null) {
                response.append(line);
                response.append('\r');
            }
            rd.close();
            //Parse json to object
            JsonParser parser = new JsonParser();
            JsonObject json = (JsonObject) parser.parse(response.toString());
            JsonObject quota_set = json.getAsJsonObject("quota_set");
            //Fill out quota
            quota.setTenant(vimInstance.getTenant());
            quota.setCores(Integer.parseInt(quota_set.get("cores").toString()));
            quota.setRam(Integer.parseInt(quota_set.get("ram").toString()));
            quota.setInstances(Integer.parseInt(quota_set.get("instances").toString()));
            quota.setFloatingIps(Integer.parseInt(quota_set.get("floating_ips").toString()));
            quota.setKeyPairs(Integer.parseInt(quota_set.get("key_pairs").toString()));
            log.info("Found Quota for tenant with name: " + vimInstance.getTenant() + " on VimInstance with name: "
                    + vimInstance.getName() + " -> Quota: " + quota);
            return quota;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw new VimDriverException(e.getMessage());
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    /**
     * @param vimInstance
     * @param server
     * @param fip
     * @return
     */
    public synchronized void associateFloatingIpToNetwork(VimInstance vimInstance, Server server,
            Map.Entry<String, String> fip) {
        log.debug("Associating FloatingIP to VM with hostname: " + server.getName() + " on VimInstance with name: "
                + vimInstance.getName());
        HttpURLConnection connection = null;
        try {
            String floatingIp = null;
            String privateIp = null;
            if (fip.getValue() != null) {
                if (fip.getValue().equals("random")) {
                    log.debug("Associating FloatingIP: defined random IP -> try to find one");
                    privateIp = server.getIps().get(fip.getKey()).get(0);
                    if (privateIp == null) {
                        log.error("Associating FloatingIP: Cannot assign FloatingIPs to server " + server.getId()
                                + " . wrong network" + fip.getKey());
                    } else {
                        floatingIp = listFreeFloatingIps(vimInstance).get(0);
                        log.debug("Got Floating ip" + floatingIp.toString());
                    }
                } else if (validate(fip.getValue())) {
                    log.debug("Associating FloatingIP: " + fip.getValue());
                    privateIp = server.getIps().get(fip.getKey()).get(0);
                    if (privateIp == null) {
                        log.error("Associating FloatingIP: Cannot assign FloatingIPs to server " + server.getId()
                                + " . wrong network" + fip.getKey());
                    } else {
                        floatingIp = fip.getValue();
                    }
                }
            } else {
                log.error("Associating FloatingIP: Cannot assign FloatingIPs to server " + server.getId()
                        + " . wrong floatingip: " + fip.getValue());
            }

            log.debug("Associating " + floatingIp + " to server: " + server.getName());
            ContextBuilder contextBuilder = ContextBuilder.newBuilder("openstack-nova")
                    .credentials(vimInstance.getUsername(), vimInstance.getPassword())
                    .endpoint(vimInstance.getAuthUrl());
            ComputeServiceContext context = contextBuilder.buildView(ComputeServiceContext.class);
            Function<Credentials, Access> auth = context.utils().injector()
                    .getInstance(Key.get(new TypeLiteral<Function<Credentials, Access>>() {
                    }));

            //Get Access and all information
            Access access = auth.apply(new Credentials.Builder<Credentials>()
                    .identity(vimInstance.getTenant() + ":" + vimInstance.getUsername())
                    .credential(vimInstance.getPassword()).build());
            //Get Tenant ID of user

            String tenant_id = access.getToken().getTenant().get().getId();
            //Get nova endpoint
            URI endpoint = null;

            log.debug("Associating FloatingIP: finding endpoint");
            for (org.jclouds.openstack.keystone.v2_0.domain.Service service : access) {
                if (service.getName().equals("neutron")) {
                    for (Endpoint end : service) {
                        endpoint = end.getPublicURL();
                        break;
                    }
                    break;
                }
            }

            log.debug("Associating FloatingIP: Endpoint is: " + endpoint);

            // Get floating Ip
            String floatingIpId = null;
            String port_id = null;
            NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NovaApi.class);
            NeutronApi neutronApi = ContextBuilder.newBuilder("openstack-neutron")
                    .endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NeutronApi.class);
            if (novaApi.getFloatingIPApi(getZone(vimInstance)).isPresent()) {
                org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi novaFloatingIPApi = novaApi
                        .getFloatingIPApi(getZone(vimInstance)).get();

                novaFloatingIPApi.addToServer(floatingIp, server.getExtId());

                server.getFloatingIps().put(fip.getKey(), floatingIp);
                log.info("Associated FloatingIP to VM with hostname: " + server.getName()
                        + " on VimInstance with name: " + vimInstance.getName() + " -> FloatingIP: " + floatingIp);
            } else {
                log.warn("Could not access floating ip using the jclouds APIs, trying with restAPI");

                floatingIpId = findFloatingIpId(floatingIp, vimInstance);

                Map<String, String> ports = listPorts(access, endpoint, vimInstance);

                port_id = ports.get(privateIp);

                URL url = new URL(endpoint + "/v2.0/floatingips/" + floatingIpId + ".json");
                connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("PUT");
                connection.setDoOutput(true);
                connection.setRequestProperty("Accept", "application/json");
                connection.setRequestProperty("User-Agent", "python-neutronclient");
                connection.setRequestProperty("X-Auth-Token", access.getToken().getId());
                OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
                String body = "{\"floatingip\": {\"port_id\": \"" + port_id + "\"}}";
                log.debug("Body is: " + body);
                out.write(body);
                out.close();
                //Get Response
                InputStream is = connection.getInputStream();
                BufferedReader rd = new BufferedReader(new InputStreamReader(is));
                StringBuilder response = new StringBuilder(); // or StringBuffer if not Java 5+
                String line;
                while ((line = rd.readLine()) != null) {
                    response.append(line);
                    response.append('\r');
                }
                rd.close();
                //Parse json to object
                log.debug("Associating FloatingIP: Response of final request is: " + response.toString());

                log.debug("Translating ip...");
                floatingIp = translateToNAT(floatingIp);

                server.getFloatingIps().put(fip.getKey(), floatingIp);
                log.info("Associated FloatingIP to VM with hostname: " + server.getName()
                        + " on VimInstance with name: " + vimInstance.getName() + " -> FloatingIP: " + floatingIp);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            //throw new VimDriverException(e.getMessage());
            log.warn(
                    "It seems that floatingApi is not present or there are not enough available floating ips, this means that "
                            + "we will not be able to assign them");
        } finally {
            if (connection != null) {
                connection.disconnect();
            }
        }
    }

    private static String translateToNAT(String floatingIp) throws UnknownHostException {

        Properties natRules = new Properties();
        try {
            File file = new File("/etc/openbaton/plugin/openstack/nat-translation-rules.properties");
            if (file.exists()) {
                natRules.load(new FileInputStream(file));
            } else {
                natRules.load(OpenstackClient.class.getResourceAsStream("/nat-translation-rules.properties"));
            }
        } catch (IOException e) {
            log.warn("no translation rules!");
            return floatingIp;
        }

        for (Map.Entry<Object, Object> entry : natRules.entrySet()) {
            String fromCidr = (String) entry.getKey();
            String toCidr = (String) entry.getValue();
            log.debug("cidr is: " + fromCidr);
            SubnetUtils utilsFrom = new SubnetUtils(fromCidr);
            SubnetUtils utilsTo = new SubnetUtils(toCidr);

            SubnetUtils.SubnetInfo subnetInfoFrom = utilsFrom.getInfo();
            SubnetUtils.SubnetInfo subnetInfoTo = utilsTo.getInfo();
            InetAddress floatingIpNetAddr = InetAddress.getByName(floatingIp);
            if (subnetInfoFrom.isInRange(floatingIp)) { //translation!

                log.debug("From networkMask " + subnetInfoFrom.getNetmask());
                log.debug("To networkMask " + subnetInfoTo.getNetmask());
                if (!subnetInfoFrom.getNetmask().equals(subnetInfoTo.getNetmask())) {
                    log.error("Not translation possible, netmasks are different");
                    return floatingIp;
                }
                byte[] host = new byte[4];
                for (int i = 0; i < floatingIpNetAddr.getAddress().length; i++) {
                    byte value = (byte) (floatingIpNetAddr.getAddress()[i]
                            | InetAddress.getByName(subnetInfoFrom.getNetmask()).getAddress()[i]);
                    if (value == -1) {
                        host[i] = 0;
                    } else {
                        host[i] = value;
                    }
                }

                byte[] netaddress = InetAddress.getByName(subnetInfoTo.getNetworkAddress()).getAddress();
                String[] result = new String[4];
                for (int i = 0; i < netaddress.length; i++) {
                    int intValue = new Byte((byte) (netaddress[i] | Byte.valueOf(host[i]))).intValue();
                    if (intValue < 0) {
                        intValue = intValue & 0xFF;
                    }
                    result[i] = String.valueOf(intValue);
                }

                return StringUtils.join(result, ".");
            }
        }
        return floatingIp;
    }

    //retrieves the ip pool name from openstack via http request
    public String getIpPoolName(VimInstance vimInstance) {
        HttpURLConnection connection = null;
        log.info("Began retrieving the name of the ip pool");
        try {
            ContextBuilder contextBuilder = ContextBuilder.newBuilder("openstack-nova")
                    .credentials(vimInstance.getUsername(), vimInstance.getPassword())
                    .endpoint(vimInstance.getAuthUrl());
            ComputeServiceContext context = contextBuilder.buildView(ComputeServiceContext.class);
            Function<Credentials, Access> auth = context.utils().injector()
                    .getInstance(Key.get(new TypeLiteral<Function<Credentials, Access>>() {
                    }));
            //Get Access and all information
            Access access = auth.apply(new Credentials.Builder<Credentials>()
                    .identity(vimInstance.getTenant() + ":" + vimInstance.getUsername())
                    .credential(vimInstance.getPassword()).build());
            //Get Tenant ID of user
            String tenant_id = access.getToken().getTenant().get().getId();
            //Get nova endpoint
            URI endpoint = null;
            for (org.jclouds.openstack.keystone.v2_0.domain.Service service : access) {
                if (service.getName().equals("nova")) {
                    for (Endpoint end : service) {
                        endpoint = end.getPublicURL();
                        break;
                    }
                    break;
                }
            }
            URL url = null;
            url = new URL(endpoint + "/os-floating-ip-pools");
            connection = (HttpURLConnection) url.openConnection();
            connection.setRequestMethod("GET");
            connection.setRequestProperty("Accept", "application/json");
            connection.setRequestProperty("X-Auth-Token", access.getToken().getId());
            InputStream is = null;
            is = connection.getInputStream();

            BufferedReader rd = new BufferedReader(new InputStreamReader(is));
            StringBuilder response = new StringBuilder(); // or StringBuffer if not Java 5+
            String line;
            while ((line = rd.readLine()) != null) {
                response.append(line);
                response.append('\r');
            }
            rd.close();

            JsonParser parser = new JsonParser();
            JsonObject json = (JsonObject) parser.parse(response.toString());

            JsonArray ip_pools = json.get("floating_ip_pools").getAsJsonArray();
            String ip_pool_name = ip_pools.get(0).getAsJsonObject().get("name").getAsString();
            log.info("Retrieved the name of ip pool: " + ip_pool_name);
            if (connection != null) {
                connection.disconnect();
            }
            return ip_pool_name;
        } catch (Exception e) {
            log.warn("An error during trying to find the name of the pool");
            return null;
        }
    }

    //allocated a number of ips from the pool
    public void get_allocated(VimInstance vimInstance, String pool_name, int ipsNeeded) {
        if (pool_name == null) {
            return;
        }

        try {
            NovaApi novaApi = ContextBuilder.newBuilder("openstack-nova").endpoint(vimInstance.getAuthUrl())
                    .credentials(vimInstance.getTenant() + ":" + vimInstance.getUsername(),
                            vimInstance.getPassword())
                    .modules(modules).overrides(overrides).buildApi(NovaApi.class);
            if (novaApi.getFloatingIPApi(getZone(vimInstance)).isPresent()) {
                org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi floatingIPApi = novaApi
                        .getFloatingIPApi(getZone(vimInstance)).get();
                while (ipsNeeded > 0) {
                    log.debug("Allocating ip from pool: " + pool_name);
                    org.jclouds.openstack.nova.v2_0.domain.FloatingIP ip = floatingIPApi
                            .allocateFromPool(pool_name);
                    if (ip == null) {
                        log.warn("There are not enough ips in the pool for instantiation");
                    }
                    log.info("Allocated new ip from pool " + pool_name + "Data about ip: " + ip.toString());
                    ipsNeeded--;
                }
            } else {
                log.warn("Could not access floating ip API");
            }
        } catch (Exception e) {
            log.warn(
                    "It was impossible to allocate more floating ips because the quota is riched or floatingapis are not "
                            + "available");
            //throw new VimDriverException(e.getMessage());
        }
        return;
    }

    private String findFloatingIpId(String floatingIp, VimInstance vimInstance)
            throws VimDriverException, IOException {
        URI endpoint = null;
        ContextBuilder contextBuilder = ContextBuilder.newBuilder("openstack-nova")
                .credentials(vimInstance.getUsername(), vimInstance.getPassword())
                .endpoint(vimInstance.getAuthUrl());
        ComputeServiceContext context = contextBuilder.buildView(ComputeServiceContext.class);
        Function<Credentials, Access> auth = context.utils().injector()
                .getInstance(Key.get(new TypeLiteral<Function<Credentials, Access>>() {
                }));

        Access access = auth.apply(new Credentials.Builder<Credentials>()
                .identity(vimInstance.getTenant() + ":" + vimInstance.getUsername())
                .credential(vimInstance.getPassword()).build());

        log.debug("listing FloatingIPs: finding endpoint");
        for (org.jclouds.openstack.keystone.v2_0.domain.Service service : access) {
            if (service.getName().equals("neutron")) {
                for (Endpoint end : service) {
                    endpoint = end.getPublicURL();
                    break;
                }
                break;
            }
        }

        HttpURLConnection connection = null;
        URL url = new URL(endpoint + "/v2.0/floatingips.json");
        connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setDoOutput(true);
        connection.setRequestProperty("Accept", "application/json");
        connection.setRequestProperty("Content-Type", "application/json");
        connection.setRequestProperty("User-Agent", "python-neutronclient");
        connection.setRequestProperty("X-Auth-Token", access.getToken().getId());

        InputStream is = connection.getInputStream();
        BufferedReader rd = new BufferedReader(new InputStreamReader(is));
        StringBuilder response = new StringBuilder(); // or StringBuffer if not Java 5+
        String line;
        while ((line = rd.readLine()) != null) {
            response.append(line);
            response.append('\r');
        }
        rd.close();
        //Parse json to object
        log.debug("Associating FloatingIP: Response of final request is: " + response.toString());

        JsonObject res = new GsonBuilder().setPrettyPrinting().create().fromJson(response.toString(),
                JsonObject.class);

        if (res.has("floatingips")) {
            for (JsonElement element : res.get("floatingips").getAsJsonArray()) {
                log.debug("FloatingIp is: " + element.getAsJsonObject());
                String floating_ip_address = element.getAsJsonObject().get("floating_ip_address").getAsString();
                log.debug("found ip: " + floating_ip_address);
                log.debug(floating_ip_address + " == " + floatingIp);
                if (floating_ip_address.equals(floatingIp)) {
                    return element.getAsJsonObject().get("id").getAsString();
                }
            }
        } else {
            log.warn("Was not possible through Openstack ReST api to retreive all the FloatingIP");
        }
        throw new VimDriverException(
                "looking for a floating ip id of a not existing floating ip. Sorry for that, we can't really implement very "
                        + "well:(");
    }

    private Map<String, String> listPorts(Access access, URI endpoint, VimInstance vimInstance) throws IOException {
        Map<String, String> result = new HashMap<>();
        HttpURLConnection connection = null;
        // curl -g -i -X GET http://192.168.145.70:9696/v2.0/ports.json -H "User-Agent: python-neutronclient" -H "Accept:
        // application/json" -H "X-Auth-Token: {SHA1}30473af2f293a9d6b758bce6a82c8061e5593781"
        URL url = new URL(endpoint + "/v2.0/ports.json");
        connection = (HttpURLConnection) url.openConnection();
        connection.setRequestMethod("GET");
        connection.setDoOutput(true);
        connection.setRequestProperty("Accept", "application/json");
        connection.setRequestProperty("User-Agent", "python-neutronclient");
        connection.setRequestProperty("X-Auth-Token", access.getToken().getId());

        InputStream is = connection.getInputStream();
        BufferedReader rd = new BufferedReader(new InputStreamReader(is));
        StringBuilder response = new StringBuilder(); // or StringBuffer if not Java 5+
        String line;
        while ((line = rd.readLine()) != null) {
            response.append(line);
            response.append('\r');
        }
        rd.close();
        //Parse json to object
        log.debug("Listing Ports: Response of final request is: " + response.toString());

        JsonObject ports = new GsonBuilder().setPrettyPrinting().create().fromJson(response.toString(),
                JsonObject.class);

        for (JsonElement port : ports.get("ports").getAsJsonArray()) {
            for (JsonElement ip : port.getAsJsonObject().get("fixed_ips").getAsJsonArray()) {
                result.put(ip.getAsJsonObject().get("ip_address").getAsString(),
                        port.getAsJsonObject().get("id").getAsString());
            }
        }

        log.debug("Found all the ports: " + result);
        return result;
    }

    @Override
    public String getType(VimInstance vimInstance) {
        return "openstack";
    }
}