/*
 * Copyright 2016-present Open Networking Laboratory
 *
 * 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.onosproject.openstacknetworking.routing;

import com.google.common.collect.ImmutableSet;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.packet.Ethernet;
import org.onlab.packet.IPv4;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpPrefix;
import org.onlab.packet.MacAddress;
import org.onlab.util.Tools;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.GroupId;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Host;
import org.onosproject.net.PortNumber;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.FlowObjectiveService;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.openstackinterface.OpenstackInterfaceService;
import org.onosproject.openstackinterface.OpenstackNetwork;
import org.onosproject.openstackinterface.OpenstackPort;
import org.onosproject.openstackinterface.OpenstackRouter;
import org.onosproject.openstackinterface.OpenstackRouterInterface;
import org.onosproject.openstackinterface.OpenstackSubnet;
import org.onosproject.openstacknetworking.AbstractVmHandler;
import org.onosproject.openstacknetworking.Constants;
import org.onosproject.openstacknetworking.OpenstackRoutingService;
import org.onosproject.openstacknetworking.RulePopulatorUtil;
import org.onosproject.openstacknode.OpenstackNode;
import org.onosproject.openstacknode.OpenstackNodeEvent;
import org.onosproject.openstacknode.OpenstackNodeListener;
import org.onosproject.openstacknode.OpenstackNodeService;
import org.onosproject.scalablegateway.api.GatewayNode;
import org.onosproject.scalablegateway.api.ScalableGatewayService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.openstacknetworking.Constants.*;
import static org.onosproject.openstacknetworking.RulePopulatorUtil.buildExtension;
import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.COMPUTE;
import static org.onosproject.openstacknode.OpenstackNodeService.NodeType.GATEWAY;

@Component(immediate = true)
@Service
public class OpenstackRoutingManager extends AbstractVmHandler implements OpenstackRoutingService {

    private final Logger log = LoggerFactory.getLogger(getClass());

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected FlowObjectiveService flowObjectiveService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected OpenstackInterfaceService openstackService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected OpenstackNodeService nodeService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected ScalableGatewayService gatewayService;

    private final ExecutorService eventExecutor = newSingleThreadScheduledExecutor(
            groupedThreads(this.getClass().getSimpleName(), "event-handler", log));
    private final InternalNodeListener nodeListener = new InternalNodeListener();

    private ApplicationId appId;

    @Activate
    protected void activate() {
        super.activate();
        appId = coreService.registerApplication(ROUTING_APP_ID);
        nodeService.addListener(nodeListener);
    }

    @Deactivate
    protected void deactivate() {
        nodeService.removeListener(nodeListener);
        log.info("stopped");
    }

    @Override
    public void createRouter(OpenstackRouter osRouter) {
    }

    @Override
    public void updateRouter(OpenstackRouter osRouter) {
        if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
            openstackService.ports().stream()
                    .filter(osPort -> osPort.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
                            osPort.deviceId().equals(osRouter.id()))
                    .forEach(osPort -> {
                        String subnetId = osPort.fixedIps().keySet().stream().findFirst().get();
                        setExternalConnection(osRouter, subnetId);
                    });

            log.info("Connected external gateway {} to router {}",
                     osRouter.gatewayExternalInfo().externalFixedIps(),
                     osRouter.name());
        } else {
            openstackService.ports().stream()
                    .filter(osPort -> osPort.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
                            osPort.deviceId().equals(osRouter.id()))
                    .forEach(osPort -> {
                        String subnetId = osPort.fixedIps().keySet().stream().findFirst().get();
                        OpenstackSubnet osSubNet = openstackService.subnet(subnetId);
                        unsetExternalConnection(osRouter, osPort.networkId(), osSubNet.cidr());
                    });

            log.info("Disconnected external gateway from router {}",
                     osRouter.name());
        }
    }

    @Override
    public void removeRouter(String osRouterId) {
        // TODO implement this
    }

    @Override
    public void addRouterInterface(OpenstackRouterInterface routerIface) {
        OpenstackRouter osRouter = openstackRouter(routerIface.id());
        OpenstackPort osPort = openstackService.port(routerIface.portId());
        if (osRouter == null || osPort == null) {
            log.warn("Failed to add router interface {}", routerIface);
            return;
        }

        setGatewayIcmp(Ip4Address.valueOf(openstackService.subnet(routerIface.subnetId()).gatewayIp()));

        setRoutes(osRouter, Optional.empty());
        if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
            String subnetId = osPort.fixedIps().keySet().stream().findFirst().get();
            setExternalConnection(osRouter, subnetId);
        }
        log.info("Connected {} to router {}", osPort.fixedIps(), osRouter.name());
    }

    @Override
    public void removeRouterInterface(OpenstackRouterInterface routerIface) {
        OpenstackRouter osRouter = openstackService.router(routerIface.id());
        if (osRouter == null) {
            log.warn("Failed to remove router interface {}", routerIface);
            return;
        }

        OpenstackSubnet osSubnet = openstackService.subnet(routerIface.subnetId());
        OpenstackNetwork osNet = openstackService.network(osSubnet.networkId());

        unsetGatewayIcmp(Ip4Address.valueOf(openstackService.subnet(routerIface.subnetId()).gatewayIp()));

        unsetRoutes(osRouter, osSubnet);

        if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
            unsetExternalConnection(osRouter, osNet.id(), osSubnet.cidr());
        }
        log.info("Disconnected {} from router {}", osSubnet.cidr(), osRouter.name());
    }

    private void setGatewayIcmp(Ip4Address gatewayIp) {
        if (gatewayIp == null) {
            return;
        }
        gatewayService.getGatewayDeviceIds().forEach(deviceId -> populateGatewayIcmpRule(gatewayIp, deviceId));
    }

    private void populateGatewayIcmpRule(Ip4Address gatewayIp, DeviceId deviceId) {
        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();

        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                .matchIPProtocol(IPv4.PROTOCOL_ICMP)
                .matchIPDst(gatewayIp.toIpPrefix());

        tBuilder.setOutput(PortNumber.CONTROLLER);

        ForwardingObjective fo = DefaultForwardingObjective.builder()
                .withSelector(sBuilder.build())
                .withTreatment(tBuilder.build())
                .withPriority(GATEWAY_ICMP_PRIORITY)
                .withFlag(ForwardingObjective.Flag.VERSATILE)
                .fromApp(appId)
                .add();

        flowObjectiveService.forward(deviceId, fo);
    }

    private void unsetGatewayIcmp(Ip4Address gatewayIp) {
        if (gatewayIp == null) {
            return;
        }
        gatewayService.getGatewayDeviceIds().forEach(deviceId -> {
            removeGatewayIcmpRule(gatewayIp, deviceId);
        });
    }

    private void removeGatewayIcmpRule(Ip4Address gatewayIp, DeviceId deviceId) {
        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();

        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                .matchIPProtocol(IPv4.PROTOCOL_ICMP)
                .matchIPDst(gatewayIp.toIpPrefix());

        RulePopulatorUtil.removeRule(flowObjectiveService, appId, deviceId, sBuilder.build(),
                ForwardingObjective.Flag.VERSATILE, GATEWAY_ICMP_PRIORITY);

    }
    private void setExternalConnection(OpenstackRouter osRouter, String osSubNetId) {
        if (!osRouter.gatewayExternalInfo().isEnablePnat()) {
            log.debug("Source NAT is disabled");
            return;
        }

        OpenstackSubnet osSubNet = openstackService.subnet(osSubNetId);
        OpenstackNetwork osNet = openstackService.network(osSubNet.networkId());
        populateExternalRules(osNet, osSubNet);
    }

    private void unsetExternalConnection(OpenstackRouter osRouter, String osNetId, String subNetCidr) {
        if (!osRouter.gatewayExternalInfo().isEnablePnat()) {
            log.debug("Source NAT is disabled");
            return;
        }

        // FIXME router interface is subnet specific, not network
        OpenstackNetwork osNet = openstackService.network(osNetId);
        removeExternalRules(osNet, subNetCidr);
    }

    private void setRoutes(OpenstackRouter osRouter, Optional<Host> host) {
        Set<OpenstackSubnet> routableSubNets = routableSubNets(osRouter.id());
        if (routableSubNets.size() < 2) {
            // no other subnet interface is connected to this router, do nothing
            return;
        }

        Set<String> routableSubNetIds = routableSubNets.stream()
                .map(OpenstackSubnet::id)
                .collect(Collectors.toSet());

        if (host.isPresent()) {
            if (!routableSubNetIds.contains(host.get().annotations().value(SUBNET_ID))) {
                // subnet of host is not connected to this router, do nothing.
                return;
            }
        }

        Set<Host> hosts = host.isPresent() ? ImmutableSet.of(host.get()) :
                Tools.stream(hostService.getHosts())
                        .filter(h -> routableSubNetIds.contains(h.annotations().value(SUBNET_ID)))
                        .collect(Collectors.toSet());

        hosts.forEach(h -> populateRoutingRules(h, routableSubNets));
    }

    private void unsetRoutes(OpenstackRouter osRouter, OpenstackSubnet osSubNet) {
        Set<OpenstackSubnet> routableSubNets = routableSubNets(osRouter.id());
        Tools.stream(hostService.getHosts())
                .filter(h -> Objects.equals(
                        h.annotations().value(NETWORK_ID), osSubNet.id()))
                .forEach(h -> removeRoutingRules(h, routableSubNets));

        routableSubNets.forEach(n -> {
            Tools.stream(hostService.getHosts())
                    .filter(h -> Objects.equals(
                            h.annotations().value(SUBNET_ID),
                            n.id()))
                    .forEach(h -> removeRoutingRules(h, ImmutableSet.of(osSubNet)));
            log.debug("Removed between {} to {}", n.name(), osSubNet.name());
        });
    }

    private OpenstackRouter openstackRouter(String routerId) {
        return openstackService.routers().stream().filter(r ->
                r.id().equals(routerId)).iterator().next();
    }

    private Optional<OpenstackPort> routerIfacePort(String osNetId, String osSubNetId) {
        // FIXME router interface is subnet specific, not network
        return openstackService.ports().stream()
                .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
                        p.networkId().equals(osNetId) &&
                        p.fixedIps().containsKey(osSubNetId))
                .findAny();
    }

    private Set<OpenstackSubnet> routableSubNets(String osRouterId) {
        return openstackService.ports().stream()
                .filter(p -> p.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE) &&
                        p.deviceId().equals(osRouterId))
                .map(p -> openstackService.subnet(p.fixedIps().keySet().stream().findFirst().get()))
                .collect(Collectors.toSet());
    }

    private void populateExternalRules(OpenstackNetwork osNet, OpenstackSubnet osSubNet) {
        populateCnodeToGateway(Long.valueOf(osNet.segmentId()), osSubNet.cidr());
        populateGatewayToController(Long.valueOf(osNet.segmentId()), osSubNet.cidr());
    }

    private void removeExternalRules(OpenstackNetwork osNet, String subNetCidr) {
        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                .matchTunnelId(Long.valueOf(osNet.segmentId()))
                .matchIPSrc(IpPrefix.valueOf(subNetCidr))
                .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);

        nodeService.completeNodes().forEach(node -> {
            ForwardingObjective.Flag flag = node.type().equals(GATEWAY) ?
                    ForwardingObjective.Flag.VERSATILE :
                    ForwardingObjective.Flag.SPECIFIC;

            RulePopulatorUtil.removeRule(
                    flowObjectiveService,
                    appId,
                    node.intBridge(),
                    sBuilder.build(),
                    flag,
                    ROUTING_RULE_PRIORITY);
        });
    }

    private void populateRoutingRules(Host host, Set<OpenstackSubnet> osSubNets) {
        String osSubNetId = host.annotations().value(SUBNET_ID);
        if (osSubNetId == null) {
            return;
        }

        DeviceId localDevice = host.location().deviceId();
        PortNumber localPort = host.location().port();
        if (!nodeService.dataIp(localDevice).isPresent()) {
            log.warn("Failed to populate L3 rules");
            return;
        }

        Map<String, String> vniMap = new HashMap<>();
        openstackService.networks().forEach(n -> vniMap.put(n.id(), n.segmentId()));

        // TODO improve pipeline, do we have to install access rules between networks
        // for every single VMs?
        osSubNets.stream().filter(osSubNet -> !osSubNet.id().equals(osSubNetId)).forEach(osSubNet -> {
            populateRoutingRulestoSameNode(
                    host.ipAddresses().stream().findFirst().get().getIp4Address(),
                    host.mac(),
                    localPort, localDevice,
                    Long.valueOf(vniMap.get(osSubNet.networkId())),
                    osSubNet.cidr());

            nodeService.completeNodes().stream()
                    .filter(node -> node.type().equals(COMPUTE))
                    .filter(node -> !node.intBridge().equals(localDevice))
                    .forEach(node -> populateRoutingRulestoDifferentNode(
                            host.ipAddresses().stream().findFirst().get().getIp4Address(),
                            Long.valueOf(vniMap.get(osSubNet.networkId())),
                            node.intBridge(),
                            nodeService.dataIp(localDevice).get().getIp4Address(),
                            osSubNet.cidr()));
        });
    }

    private void removeRoutingRules(Host host, Set<OpenstackSubnet> osSubNets) {
        String osSubNetId = host.annotations().value(SUBNET_ID);
        if (osSubNetId == null) {
            return;
        }

        Map<String, String> vniMap = new HashMap<>();
        openstackService.networks().forEach(n -> vniMap.put(n.id(), n.segmentId()));

        osSubNets.stream().filter(osSubNet -> !osSubNet.id().equals(osSubNetId)).forEach(osSubNet -> {
            TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
            sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                    .matchIPDst(host.ipAddresses().stream().findFirst().get().toIpPrefix())
                    .matchIPSrc(IpPrefix.valueOf(osSubNet.cidr()))
                    .matchTunnelId(Long.valueOf(vniMap.get(osSubNet.networkId())));

            nodeService.completeNodes().stream()
                    .filter(node -> node.type().equals(COMPUTE))
                    .forEach(node -> RulePopulatorUtil.removeRule(
                            flowObjectiveService,
                            appId,
                            node.intBridge(),
                            sBuilder.build(),
                            ForwardingObjective.Flag.SPECIFIC,
                            EW_ROUTING_RULE_PRIORITY));
        });
        log.debug("Removed routing rule from {} to {}", host, osSubNets);
    }

    private void populateGatewayToController(long vni, String subNetCidr) {
        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();

        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                .matchTunnelId(vni)
                .matchIPSrc(IpPrefix.valueOf(subNetCidr))
                .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);
        tBuilder.setOutput(PortNumber.CONTROLLER);

        ForwardingObjective fo = DefaultForwardingObjective.builder()
                .withSelector(sBuilder.build())
                .withTreatment(tBuilder.build())
                .withFlag(ForwardingObjective.Flag.VERSATILE)
                .withPriority(ROUTING_RULE_PRIORITY)
                .fromApp(appId)
                .add();

        gatewayService.getGatewayDeviceIds().forEach(deviceId -> flowObjectiveService.forward(deviceId, fo));
    }

    private void populateCnodeToGateway(long vni, String subnetCidr) {
        nodeService.completeNodes().stream()
                .filter(node -> node.type().equals(COMPUTE))
                .forEach(node -> populateRuleToGateway(
                        node.intBridge(),
                        gatewayService.getGatewayGroupId(node.intBridge()),
                        vni, subnetCidr));
    }

    private void populateRuleToGateway(DeviceId deviceId, GroupId groupId, long vni, String cidr) {
        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();

        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                .matchTunnelId(vni)
                .matchIPSrc(IpPrefix.valueOf(cidr))
                .matchEthDst(Constants.DEFAULT_GATEWAY_MAC);

        tBuilder.group(groupId);
        ForwardingObjective fo = DefaultForwardingObjective.builder()
                .withSelector(sBuilder.build())
                .withTreatment(tBuilder.build())
                .withFlag(ForwardingObjective.Flag.SPECIFIC)
                .withPriority(ROUTING_RULE_PRIORITY)
                .fromApp(appId)
                .add();

        flowObjectiveService.forward(deviceId, fo);
    }

    private void populateRoutingRulestoDifferentNode(Ip4Address vmIp, long vni,
                                                     DeviceId deviceId, Ip4Address hostIp,
                                                     String cidr) {
        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();

        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                .matchTunnelId(vni)
                .matchIPSrc(IpPrefix.valueOf(cidr))
                .matchIPDst(vmIp.toIpPrefix());
        tBuilder.extension(buildExtension(deviceService, deviceId, hostIp), deviceId)
                .setOutput(nodeService.tunnelPort(deviceId).get());

        ForwardingObjective fo = DefaultForwardingObjective.builder()
                .withSelector(sBuilder.build())
                .withTreatment(tBuilder.build())
                .withPriority(EW_ROUTING_RULE_PRIORITY)
                .withFlag(ForwardingObjective.Flag.SPECIFIC)
                .fromApp(appId)
                .add();

        flowObjectiveService.forward(deviceId, fo);
    }

    private void populateRoutingRulestoSameNode(Ip4Address vmIp, MacAddress vmMac,
                                                PortNumber port, DeviceId deviceId, long vni,
                                                String cidr) {
        TrafficSelector.Builder sBuilder = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();

        // FIXME: we need to check the VNI of the dest IP also just in case...
        sBuilder.matchEthType(Ethernet.TYPE_IPV4)
                .matchIPDst(vmIp.toIpPrefix())
                .matchIPSrc(IpPrefix.valueOf(cidr))
                .matchTunnelId(vni);

        tBuilder.setEthDst(vmMac)
                .setOutput(port);

        ForwardingObjective fo = DefaultForwardingObjective.builder()
                .withSelector(sBuilder.build())
                .withTreatment(tBuilder.build())
                .withPriority(EW_ROUTING_RULE_PRIORITY)
                .withFlag(ForwardingObjective.Flag.SPECIFIC)
                .fromApp(appId)
                .add();

        flowObjectiveService.forward(deviceId, fo);
    }

    private void reloadRoutingRules() {
        eventExecutor.execute(() -> openstackService.ports().stream()
                .filter(osPort -> osPort.deviceOwner().equals(DEVICE_OWNER_ROUTER_INTERFACE))
                .forEach(osPort -> {
                    OpenstackRouter osRouter = openstackRouter(osPort.deviceId());

                    setGatewayIcmp(Ip4Address.valueOf(openstackService
                            .subnet(osPort.fixedIps().keySet().stream().findAny().get()).gatewayIp()));

                    setRoutes(osRouter, Optional.empty());
                    if (osRouter.gatewayExternalInfo().externalFixedIps().size() > 0) {
                        String subnetId = osPort.fixedIps().keySet().stream().findFirst().get();
                        setExternalConnection(osRouter, subnetId);
                    }
                }));
    }

    @Override
    protected void hostDetected(Host host) {
        String osNetId = host.annotations().value(NETWORK_ID);
        String osSubNetId = host.annotations().value(SUBNET_ID);
        Optional<OpenstackPort> routerIface = routerIfacePort(osNetId, osSubNetId);
        if (!routerIface.isPresent()) {
            return;
        }
        eventExecutor.execute(() -> setRoutes(
                openstackRouter(routerIface.get().deviceId()),
                Optional.of(host)));
    }

    @Override
    protected void hostRemoved(Host host) {
        String osNetId = host.annotations().value(NETWORK_ID);
        String osSubNetId = host.annotations().value(SUBNET_ID);
        Optional<OpenstackPort> routerIface = routerIfacePort(osNetId, osSubNetId);
        if (!routerIface.isPresent()) {
            return;
        }
        Set<OpenstackSubnet> routableSubNets = routableSubNets(routerIface.get().deviceId());
        eventExecutor.execute(() -> removeRoutingRules(host, routableSubNets));
    }

    @Override
    public void reinstallVmFlow(Host host) {
        if (host == null) {
            hostService.getHosts().forEach(h -> {
                hostDetected(h);
                log.info("Re-Install data plane flow of virtual machine {}", h);
            });
        } else {
            hostDetected(host);
            log.info("Re-Install data plane flow of virtual machine {}", host);
        }
    }

    @Override
    public void purgeVmFlow(Host host) {
        if (host == null) {
            hostService.getHosts().forEach(h -> {
                hostRemoved(h);
                log.info("Purge data plane flow of virtual machine {}", h);
            });
        } else {
            hostRemoved(host);
            log.info("Purge data plane flow of virtual machine {}", host);
        }
    }

    private class InternalNodeListener implements OpenstackNodeListener {

        @Override
        public void event(OpenstackNodeEvent event) {
            OpenstackNode node = event.node();

            switch (event.type()) {
                case COMPLETE:
                    log.info("COMPLETE node {} detected", node.hostname());
                    eventExecutor.execute(() -> {
                        if (node.type() == GATEWAY) {
                            GatewayNode gnode = GatewayNode.builder()
                                    .gatewayDeviceId(node.intBridge())
                                    .dataIpAddress(node.dataIp().getIp4Address())
                                    .uplinkIntf(node.externalPortName().get())
                                    .build();
                            gatewayService.addGatewayNode(gnode);
                        }
                        reloadRoutingRules();
                    });
                    break;
                case INIT:
                case DEVICE_CREATED:
                case INCOMPLETE:
                    eventExecutor.execute(() -> {
                        if (node.type() == GATEWAY) {
                            GatewayNode gnode = GatewayNode.builder()
                                    .gatewayDeviceId(node.intBridge())
                                    .dataIpAddress(node.dataIp().getIp4Address())
                                    .uplinkIntf(node.externalPortName().get())
                                    .build();
                            gatewayService.deleteGatewayNode(gnode);
                        }
                        reloadRoutingRules();
                    });
                default:
                    break;
            }
        }
    }
}
