You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mu...@apache.org on 2014/03/14 11:38:00 UTC

[47/54] [abbrv] git commit: updated refs/heads/distributedrouter to 42b553e

introduce OvsNetworkTopologyGuru that has convinenace functions to
   - get the hosts on which VPC spans given vpc id
   - get the VM's in the VPC
   - get the hosts on which a network spans
   - get the VPC's to which a hosts is part of
   - get VM's of a VPC on a hosts

introduces capability to build a physical toplogy representation of a
VPC. This json file is encapsulated in
OvsVpcPhysicalTopologyConfigCommand, and is used to send full topology
to hypervisor hosts. On hypervisor this json config can be used to setup
tunnels, configure bridge, add flow rules etc

Ovs GURU, to use different broasdcast scheme VS://vpcid.gerkey for the
networks in VPC that use distributed routing

each VIF and tunnel interface to carry the network UUID in other/options
config


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/8dcce6aa
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/8dcce6aa
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/8dcce6aa

Branch: refs/heads/distributedrouter
Commit: 8dcce6aa338ca8b5ac343f79822baabfc578631f
Parents: 73b6c1b
Author: Murali Reddy <mu...@gmail.com>
Authored: Mon Mar 10 12:52:30 2014 +0530
Committer: Murali Reddy <mu...@gmail.com>
Committed: Fri Mar 14 15:58:19 2014 +0530

----------------------------------------------------------------------
 api/src/com/cloud/agent/api/to/NicTO.java       |   8 +
 .../kvm/resource/LibvirtComputingResource.java  |  34 +-
 .../xen/resource/CitrixResourceBase.java        |  95 +++--
 .../cloudstack/ovs/spring-ovs-context.xml       |   2 +-
 .../cloud/agent/api/OvsCreateTunnelCommand.java |  19 +-
 .../agent/api/OvsDestroyBridgeCommand.java      |  10 +-
 .../agent/api/OvsDestroyTunnelCommand.java      |  10 +-
 .../cloud/agent/api/OvsSetupBridgeCommand.java  |  10 +-
 .../OvsVpcPhysicalTopologyConfigCommand.java    | 127 +++++++
 .../com/cloud/network/element/OvsElement.java   |  35 +-
 .../cloud/network/guru/OvsGuestNetworkGuru.java |  17 +-
 .../network/ovs/OvsNetworkTopologyGuru.java     |  49 +++
 .../network/ovs/OvsNetworkTopologyGuruImpl.java |  74 ++++
 .../com/cloud/network/ovs/OvsTunnelManager.java |  16 +-
 .../cloud/network/ovs/OvsTunnelManagerImpl.java | 356 ++++++++++++++-----
 .../com/cloud/network/ovs/dao/OvsTunnel.java    |  24 ++
 .../network/ovs/dao/OvsTunnelNetworkVO.java     |   2 +-
 scripts/vm/hypervisor/xenserver/ovstunnel       |   2 +
 .../cloud/hypervisor/HypervisorGuruBase.java    |   7 +
 19 files changed, 737 insertions(+), 160 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/api/src/com/cloud/agent/api/to/NicTO.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/agent/api/to/NicTO.java b/api/src/com/cloud/agent/api/to/NicTO.java
index bd8f24e..67660c8 100644
--- a/api/src/com/cloud/agent/api/to/NicTO.java
+++ b/api/src/com/cloud/agent/api/to/NicTO.java
@@ -80,4 +80,12 @@ public class NicTO extends NetworkTO {
     public List<String> getNicSecIps() {
         return nicSecIps;
     }
+
+    public String getNetworkUuid() {
+        return super.getUuid();
+    }
+
+    public void setNetworkUuid(String uuid) {
+        super.setUuid(uuid);
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
index cdeedfe..c1a7721 100755
--- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
+++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java
@@ -1388,23 +1388,22 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
     }
 
     private Answer execute(OvsSetupBridgeCommand cmd) {
-        findOrCreateTunnelNetwork(cmd.getKey());
+        findOrCreateTunnelNetwork(cmd.getBridgeName());
         configureTunnelNetwork(cmd.getNetworkId(), cmd.getHostId(),
-                cmd.getKey());
+                cmd.getBridgeName());
         s_logger.debug("OVS Bridge configured");
         return new Answer(cmd, true, null);
     }
 
     private Answer execute(OvsDestroyBridgeCommand cmd) {
-        destroyTunnelNetwork(cmd.getKey());
+        destroyTunnelNetwork(cmd.getBridgeName());
         s_logger.debug("OVS Bridge destroyed");
         return new Answer(cmd, true, null);
     }
 
-    private synchronized void destroyTunnelNetwork(int key) {
+    private synchronized void destroyTunnelNetwork(String bridge) {
         try {
-            findOrCreateTunnelNetwork(key);
-            String bridge = "OVSTunnel" + key;
+            findOrCreateTunnelNetwork(bridge);
             Script cmd = new Script(_ovsTunnelPath, _timeout, s_logger);
             cmd.add("destroy_ovs_bridge");
             cmd.add("--bridge", bridge);
@@ -1423,9 +1422,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
         }
     }
 
-    private synchronized boolean findOrCreateTunnelNetwork(long key) {
+    private synchronized boolean findOrCreateTunnelNetwork(String nwName) {
         try {
-            String nwName = "OVSTunnel" + key;
             if (checkNetwork(nwName)) {
                 return true;
             }
@@ -1443,10 +1441,9 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
     }
 
     private synchronized boolean configureTunnelNetwork(long networkId,
-            long hostId, int key) {
+            long hostId, String nwName) {
         try {
-            findOrCreateTunnelNetwork(key);
-            String nwName = "OVSTunnel" + key;
+            findOrCreateTunnelNetwork(nwName);
             String configuredHosts = Script
                     .runSimpleBashScript("ovs-vsctl get bridge " + nwName
                             + " other_config:ovs_host_setup");
@@ -1463,7 +1460,7 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
             if (!configured) {
                 Script cmd = new Script(_ovsTunnelPath, _timeout, s_logger);
                 cmd.add("setup_ovs_bridge");
-                cmd.add("--key", String.valueOf(key));
+                cmd.add("--key", nwName);
                 cmd.add("--cs_host_id", ((Long)hostId).toString());
                 cmd.add("--bridge", nwName);
                 String result = cmd.execute();
@@ -1481,16 +1478,16 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
     }
 
     private OvsCreateTunnelAnswer execute(OvsCreateTunnelCommand cmd) {
-        String bridge = "OVSTunnel" + cmd.getKey();
+        String bridge = cmd.getNetworkName();
         try {
-            if (!findOrCreateTunnelNetwork(cmd.getKey())) {
+            if (!findOrCreateTunnelNetwork(bridge)) {
                 s_logger.debug("Error during bridge setup");
                 return new OvsCreateTunnelAnswer(cmd, false,
                         "Cannot create network", bridge);
             }
 
             configureTunnelNetwork(cmd.getNetworkId(), cmd.getFrom(),
-                    cmd.getKey());
+                    cmd.getNetworkName());
             Script command = new Script(_ovsTunnelPath, _timeout, s_logger);
             command.add("create_tunnel");
             command.add("--bridge", bridge);
@@ -1515,16 +1512,15 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
 
     private Answer execute(OvsDestroyTunnelCommand cmd) {
         try {
-            if (!findOrCreateTunnelNetwork(cmd.getKey())) {
+            if (!findOrCreateTunnelNetwork(cmd.getBridgeName())) {
                 s_logger.warn("Unable to find tunnel network for GRE key:"
-                        + cmd.getKey());
+                        + cmd.getBridgeName());
                 return new Answer(cmd, false, "No network found");
             }
 
-            String bridge = "OVSTunnel" + cmd.getKey();
             Script command = new Script(_ovsTunnelPath, _timeout, s_logger);
             command.add("destroy_tunnel");
-            command.add("--bridge", bridge);
+            command.add("--bridge", cmd.getBridgeName());
             command.add("--iface_name", cmd.getInPortName());
             String result = command.execute();
             if (result == null) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
index 9103b59..3e7dfaf 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
@@ -148,6 +148,7 @@ import com.cloud.agent.api.OvsFetchInterfaceCommand;
 import com.cloud.agent.api.OvsSetTagAndFlowAnswer;
 import com.cloud.agent.api.OvsSetTagAndFlowCommand;
 import com.cloud.agent.api.OvsSetupBridgeCommand;
+import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand;
 import com.cloud.agent.api.PerformanceMonitorAnswer;
 import com.cloud.agent.api.PerformanceMonitorCommand;
 import com.cloud.agent.api.PingCommand;
@@ -507,6 +508,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
             return execute((OvsSetTagAndFlowCommand)cmd);
         } else if (clazz == OvsDeleteFlowCommand.class) {
             return execute((OvsDeleteFlowCommand)cmd);
+        } else if (clazz == OvsVpcPhysicalTopologyConfigCommand.class) {
+            return execute((OvsVpcPhysicalTopologyConfigCommand) cmd);
         } else if (clazz == CleanupNetworkRulesCmd.class) {
             return execute((CleanupNetworkRulesCmd)cmd);
         } else if (clazz == NetworkRulesSystemVmCommand.class) {
@@ -964,15 +967,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
     /**
      * This method just creates a XenServer network following the tunnel network naming convention
      */
-    private synchronized Network findOrCreateTunnelNetwork(Connection conn, long key) {
+    private synchronized Network findOrCreateTunnelNetwork(Connection conn, String nwName) {
         try {
-            String nwName = "OVSTunnel" + key;
             Network nw = null;
             Network.Record rec = new Network.Record();
             Set<Network> networks = Network.getByNameLabel(conn, nwName);
 
             if (networks.size() == 0) {
-                rec.nameDescription = "tunnel network id# " + key;
+                rec.nameDescription = "tunnel network id# " + nwName;
                 rec.nameLabel = nwName;
                 //Initialize the ovs-host-setup to avoid error when doing get-param in plugin
                 Map<String, String> otherConfig = new HashMap<String, String>();
@@ -981,7 +983,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 nw = Network.create(conn, rec);
                 // Plug dom0 vif only when creating network
                 if (!is_xcp())
-                    enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + key);
+                    enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + nwName);
                 s_logger.debug("### Xen Server network for tunnels created:" + nwName);
             } else {
                 nw = networks.iterator().next();
@@ -997,10 +999,10 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
     /**
      * This method creates a XenServer network and configures it for being used as a L2-in-L3 tunneled network
      */
-    private synchronized Network configureTunnelNetwork(Connection conn, long networkId, long hostId, int key) {
+    private synchronized Network configureTunnelNetwork(Connection conn, long networkId, long hostId, String bridgeName) {
         try {
-            Network nw = findOrCreateTunnelNetwork(conn, key);
-            String nwName = "OVSTunnel" + key;
+            Network nw = findOrCreateTunnelNetwork(conn, bridgeName);
+            String nwName = bridgeName;
             //Invoke plugin to setup the bridge which will be used by this network
             String bridge = nw.getBridge(conn);
             Map<String, String> nwOtherConfig = nw.getOtherConfig(conn);
@@ -1018,11 +1020,20 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
             if (!configured) {
                 // Plug dom0 vif only if not done before for network and host
                 if (!is_xcp())
-                    enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + key);
-                String result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge", "bridge", bridge,
-                        "key", String.valueOf(key),
-                        "xs_nw_uuid", nw.getUuid(conn),
-                        "cs_host_id", ((Long)hostId).toString());
+                    enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + bridgeName);
+                String result;
+                if (bridgeName.startsWith("OVS-DR-VPC-Bridge")) {
+                    result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge_for_distributed_routing", "bridge", bridge,
+                            "key", bridgeName,
+                            "xs_nw_uuid", nw.getUuid(conn),
+                            "cs_host_id", ((Long)hostId).toString());
+                } else {
+                    result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge", "bridge", bridge,
+                            "key", bridgeName,
+                            "xs_nw_uuid", nw.getUuid(conn),
+                            "cs_host_id", ((Long)hostId).toString());
+                }
+
                 //Note down the fact that the ovs bridge has been setup
                 String[] res = result.split(":");
                 if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) {
@@ -1037,9 +1048,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         }
     }
 
-    private synchronized void destroyTunnelNetwork(Connection conn, int key) {
+    private synchronized void destroyTunnelNetwork(Connection conn, String bridgeName) {
         try {
-            Network nw = findOrCreateTunnelNetwork(conn, key);
+            Network nw = findOrCreateTunnelNetwork(conn, bridgeName);
             String bridge = nw.getBridge(conn);
             String result = callHostPlugin(conn, "ovstunnel", "destroy_ovs_bridge", "bridge", bridge);
             String[] res = result.split(":");
@@ -1079,8 +1090,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
                 _isOvs = true;
                 return setupvSwitchNetwork(conn);
             } else {
-                long vnetId = Long.parseLong(BroadcastDomainType.getValue(uri));
-                return findOrCreateTunnelNetwork(conn, vnetId);
+                return findOrCreateTunnelNetwork(conn, getOvsTunnelNetworkName(BroadcastDomainType.getValue(uri)));
             }
         } else if (type == BroadcastDomainType.Storage) {
             if (uri == null) {
@@ -1102,6 +1112,19 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         throw new CloudRuntimeException("Unable to support this type of network broadcast domain: " + nic.getBroadcastUri());
     }
 
+    private String getOvsTunnelNetworkName(String broadcastUri) {
+        if (broadcastUri.contains(".")) {
+            String[] parts = broadcastUri.split(".");
+            return "OVS-DR-VPC-Bridge"+parts[0];
+         } else {
+            try {
+                return "OVSTunnel" + broadcastUri;
+            } catch (Exception e) {
+                return null;
+            }
+         }
+    }
+
     protected VIF createVif(Connection conn, String vmName, VM vm, VirtualMachineTO vmSpec, NicTO nic) throws XmlRpcException, XenAPIException {
         assert (nic.getUuid() != null) : "Nic should have a uuid value";
 
@@ -1122,7 +1145,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         if (vmSpec != null) {
             vifr.otherConfig.put("cloudstack-vm-id", vmSpec.getUuid());
         }
-
+        vifr.otherConfig.put("cloudstack-network-id", nic.getNetworkUuid());
         vifr.network = getNetwork(conn, nic);
 
         if (nic.getNetworkRateMbps() != null && nic.getNetworkRateMbps().intValue() != -1) {
@@ -5220,15 +5243,15 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
 
     private Answer execute(OvsSetupBridgeCommand cmd) {
         Connection conn = getConnection();
-        findOrCreateTunnelNetwork(conn, cmd.getKey());
-        configureTunnelNetwork(conn, cmd.getNetworkId(), cmd.getHostId(), cmd.getKey());
+        findOrCreateTunnelNetwork(conn, cmd.getBridgeName());
+        configureTunnelNetwork(conn, cmd.getNetworkId(), cmd.getHostId(), cmd.getBridgeName());
         s_logger.debug("OVS Bridge configured");
         return new Answer(cmd, true, null);
     }
 
     private Answer execute(OvsDestroyBridgeCommand cmd) {
         Connection conn = getConnection();
-        destroyTunnelNetwork(conn, cmd.getKey());
+        destroyTunnelNetwork(conn, cmd.getBridgeName());
         s_logger.debug("OVS Bridge destroyed");
         return new Answer(cmd, true, null);
     }
@@ -5236,14 +5259,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
     private Answer execute(OvsDestroyTunnelCommand cmd) {
         Connection conn = getConnection();
         try {
-            Network nw = findOrCreateTunnelNetwork(conn, cmd.getNetworkId());
+            Network nw = findOrCreateTunnelNetwork(conn, cmd.getBridgeName());
             if (nw == null) {
-                s_logger.warn("Unable to find tunnel network for GRE key:" + cmd.getKey());
+                s_logger.warn("Unable to find tunnel network for GRE key:" + cmd.getBridgeName());
                 return new Answer(cmd, false, "No network found");
             }
 
             String bridge = nw.getBridge(conn);
-            String result = callHostPlugin(conn, "ovstunnel", "destroy_tunnel", "bridge", bridge, "in_port", cmd.getInPortName());
+            String result = callHostPlugin(conn, "ovstunnel", "configure_ovs_bridge_for_network_topology", "bridge", bridge, "in_port", cmd.getInPortName());
             if (result.equalsIgnoreCase("SUCCESS")) {
                 return new Answer(cmd, true, result);
             } else {
@@ -5255,6 +5278,22 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         }
     }
 
+    public Answer execute(OvsVpcPhysicalTopologyConfigCommand cmd) {
+        Connection conn = getConnection();
+        try {
+            String result = callHostPlugin(conn, "ovstunnel", "configure_ovs_bridge_for_network_topology", "bridge",
+                    cmd.getBridgeName(), "host-id", ((Long)cmd.getHostId()).toString());
+            if (result.equalsIgnoreCase("SUCCESS")) {
+                return new Answer(cmd, true, result);
+            } else {
+                return new Answer(cmd, false, result);
+            }
+        } catch  (Exception e) {
+            s_logger.warn("caught exception while updating host with latest VPC topology", e);
+            return new Answer(cmd, false, e.getMessage());
+        }
+    }
+
     private Answer execute(UpdateHostPasswordCommand cmd) {
         _password.add(cmd.getNewPassword());
         return new Answer(cmd, true, null);
@@ -5264,17 +5303,19 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         Connection conn = getConnection();
         String bridge = "unknown";
         try {
-            Network nw = findOrCreateTunnelNetwork(conn, cmd.getKey());
+            Network nw = findOrCreateTunnelNetwork(conn, cmd.getNetworkName());
             if (nw == null) {
                 s_logger.debug("Error during bridge setup");
                 return new OvsCreateTunnelAnswer(cmd, false, "Cannot create network", bridge);
             }
 
-            configureTunnelNetwork(conn, cmd.getNetworkId(), cmd.getFrom(), cmd.getKey());
+            configureTunnelNetwork(conn, cmd.getNetworkId(), cmd.getFrom(), cmd.getNetworkName());
             bridge = nw.getBridge(conn);
             String result =
-                    callHostPlugin(conn, "ovstunnel", "create_tunnel", "bridge", bridge, "remote_ip", cmd.getRemoteIp(), "key", cmd.getKey().toString(), "from",
-                            cmd.getFrom().toString(), "to", cmd.getTo().toString());
+                    callHostPlugin(conn, "ovstunnel", "create_tunnel", "bridge", bridge, "remote_ip", cmd.getRemoteIp(),
+                            "key", cmd.getKey().toString(), "from",
+                            cmd.getFrom().toString(), "to", cmd.getTo().toString(), "cloudstack-network-id",
+                            cmd.getNetworkUuid());
             String[] res = result.split(":");
             if (res.length == 2 && res[0].equalsIgnoreCase("SUCCESS")) {
                 return new OvsCreateTunnelAnswer(cmd, true, result, res[1], bridge);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/plugins/network-elements/ovs/resources/META-INF/cloudstack/ovs/spring-ovs-context.xml
----------------------------------------------------------------------
diff --git a/plugins/network-elements/ovs/resources/META-INF/cloudstack/ovs/spring-ovs-context.xml b/plugins/network-elements/ovs/resources/META-INF/cloudstack/ovs/spring-ovs-context.xml
index e60d93e..fa56d5d 100644
--- a/plugins/network-elements/ovs/resources/META-INF/cloudstack/ovs/spring-ovs-context.xml
+++ b/plugins/network-elements/ovs/resources/META-INF/cloudstack/ovs/spring-ovs-context.xml
@@ -38,5 +38,5 @@
     <bean id="ovsTunnelManagerImpl" class="com.cloud.network.ovs.OvsTunnelManagerImpl" />
     <bean id="ovsTunnelInterfaceDaoImpl" class="com.cloud.network.ovs.dao.OvsTunnelInterfaceDaoImpl" />
     <bean id="ovsTunnelNetworkDaoImpl" class="com.cloud.network.ovs.dao.OvsTunnelNetworkDaoImpl" />
-    
+    <bean id="ovsNetworkTopologyGuruImpl" class="com.cloud.network.ovs.OvsNetworkTopologyGuruImpl"/>
 </beans>

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsCreateTunnelCommand.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsCreateTunnelCommand.java b/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsCreateTunnelCommand.java
index 7f151fb..3e08531 100644
--- a/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsCreateTunnelCommand.java
+++ b/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsCreateTunnelCommand.java
@@ -20,10 +20,13 @@ package com.cloud.agent.api;
 public class OvsCreateTunnelCommand extends Command {
     Integer key;
     String remoteIp;
+    String networkName;
     Long from;
     Long to;
     long networkId;
 
+    String networkUuid;
+
     // for debug info
     String fromIp;
 
@@ -33,13 +36,15 @@ public class OvsCreateTunnelCommand extends Command {
     }
 
     public OvsCreateTunnelCommand(String remoteIp, Integer key, Long from,
-            Long to, long networkId, String fromIp) {
+            Long to, long networkId, String fromIp, String networkName, String networkUuid) {
         this.remoteIp = remoteIp;
         this.key = key;
         this.from = from;
         this.to = to;
         this.networkId = networkId;
         this.fromIp = fromIp;
+        this.networkName = networkName;
+        this.networkUuid = networkUuid;
     }
 
     public Integer getKey() {
@@ -66,4 +71,16 @@ public class OvsCreateTunnelCommand extends Command {
         return fromIp;
     }
 
+    public String getNetworkName() {
+        return networkName;
+    }
+
+
+    public String getNetworkUuid() {
+        return networkUuid;
+    }
+
+    public void setNetworkUuid(String networkUuid) {
+        this.networkUuid = networkUuid;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsDestroyBridgeCommand.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsDestroyBridgeCommand.java b/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsDestroyBridgeCommand.java
index 59b50be..f9205c5 100644
--- a/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsDestroyBridgeCommand.java
+++ b/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsDestroyBridgeCommand.java
@@ -21,19 +21,19 @@ package com.cloud.agent.api;
 public class OvsDestroyBridgeCommand extends Command {
 
     Long networkId;
-    Integer key;
+    String name;
 
-    public OvsDestroyBridgeCommand(Long networkId, Integer key) {
+    public OvsDestroyBridgeCommand(Long networkId, String name) {
         this.networkId = networkId;
-        this.key = key;
+        this.name = name;
     }
 
     public Long getNetworkId() {
         return networkId;
     }
 
-    public Integer getKey() {
-        return key;
+    public String getBridgeName() {
+        return name;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsDestroyTunnelCommand.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsDestroyTunnelCommand.java b/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsDestroyTunnelCommand.java
index 4776a07..9fc6c37 100644
--- a/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsDestroyTunnelCommand.java
+++ b/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsDestroyTunnelCommand.java
@@ -20,14 +20,14 @@ package com.cloud.agent.api;
 public class OvsDestroyTunnelCommand extends Command {
 
     Long networkId;
-    Integer key;
+    String networkName;
     String inPortName;
 
-    public OvsDestroyTunnelCommand(Long networkId, Integer key,
+    public OvsDestroyTunnelCommand(Long networkId, String networkName,
             String inPortName) {
         this.networkId = networkId;
         this.inPortName = inPortName;
-        this.key = key;
+        this.networkName = networkName;
     }
 
     public Long getNetworkId() {
@@ -38,8 +38,8 @@ public class OvsDestroyTunnelCommand extends Command {
         return inPortName;
     }
 
-    public Integer getKey() {
-        return key;
+    public String getBridgeName() {
+        return networkName;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsSetupBridgeCommand.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsSetupBridgeCommand.java b/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsSetupBridgeCommand.java
index e3390f3..a104598 100644
--- a/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsSetupBridgeCommand.java
+++ b/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsSetupBridgeCommand.java
@@ -19,7 +19,7 @@ package com.cloud.agent.api;
 
 
 public class OvsSetupBridgeCommand extends Command {
-    Integer key;
+    String name;
     Long hostId;
     Long networkId;
 
@@ -28,14 +28,14 @@ public class OvsSetupBridgeCommand extends Command {
         return true;
     }
 
-    public OvsSetupBridgeCommand(Integer key, Long hostId, Long networkId) {
-        this.key = key;
+    public OvsSetupBridgeCommand(String name, Long hostId, Long networkId) {
+        this.name = name;
         this.hostId = hostId;
         this.networkId = networkId;
     }
 
-    public Integer getKey() {
-        return key;
+    public String getBridgeName() {
+        return name;
     }
 
     public Long getHostId() {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsVpcPhysicalTopologyConfigCommand.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsVpcPhysicalTopologyConfigCommand.java b/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsVpcPhysicalTopologyConfigCommand.java
new file mode 100644
index 0000000..35d4c6e
--- /dev/null
+++ b/plugins/network-elements/ovs/src/com/cloud/agent/api/OvsVpcPhysicalTopologyConfigCommand.java
@@ -0,0 +1,127 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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 com.cloud.agent.api;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+/**
+ * This command represents view of how a VPC is laid out (on which hosts, which VM is on which host etc)
+ * on the physical infrastructure.
+ */
+public class OvsVpcPhysicalTopologyConfigCommand extends Command {
+
+    VpcConfig vpcConfig =null;
+    long hostId;
+    String bridgeName;
+
+    public static class Host {
+        long hostId;
+        String ipAddress;
+
+        public Host (long hostId, String ipAddress) {
+            this.hostId = hostId;
+            this.ipAddress = ipAddress;
+        }
+    }
+
+    public static class Nic {
+        String ipAddress;
+        String macAddress;
+        String networkUuid;
+        public Nic (String ipAddress, String macAddress, String networkUuid) {
+            this.ipAddress = ipAddress;
+            this.macAddress = macAddress;
+            this.networkUuid = networkUuid;
+        }
+    }
+
+    public static class Tier {
+        long greKey;
+        String networkUuid;
+        String gatewayIp;
+        String gatewayMac;
+        String cidr;
+        public Tier(long greKey, String networkUuid, String gatewayIp, String gatewayMac, String cidr) {
+            this.greKey = greKey;
+            this.networkUuid = networkUuid;
+            this.gatewayIp = gatewayIp;
+            this.gatewayMac = gatewayMac;
+            this.cidr = cidr;
+        }
+    }
+
+    public static class Vm {
+        long hostId;
+        Nic[] nics;
+        public Vm(long hostId, Nic[] nics) {
+            this.hostId = hostId;
+            this.nics = nics;
+        }
+    }
+
+    public static class Vpc {
+        String cidr;
+        Host[] hosts;
+        Tier[] tiers;
+        Vm[]  vms;
+        public Vpc(Host[] hosts, Tier[] tiers, Vm[] vms, String cidr) {
+            this.hosts = hosts;
+            this.tiers = tiers;
+            this.vms = vms;
+            this.cidr = cidr;
+        }
+    }
+
+    public static class VpcConfig {
+        Vpc vpc;
+        public VpcConfig(Vpc vpc) {
+            this.vpc = vpc;
+        }
+    }
+
+    public OvsVpcPhysicalTopologyConfigCommand(Host[] hosts, Tier[] tiers, Vm[] vms, String cidr) {
+        Vpc vpc = new Vpc(hosts, tiers, vms, cidr);
+        vpcConfig = new VpcConfig(vpc);
+    }
+
+    public String getjsonVpcConfig() {
+        Gson gson = new GsonBuilder().create();
+        return gson.toJson(vpcConfig).toLowerCase();
+    }
+
+    @Override
+    public boolean executeInSequence() {
+        return false;
+    }
+
+    public void setHostId(long hostId) {
+        this.hostId = hostId;
+    }
+
+    public long getHostId() {
+        return hostId;
+    }
+
+    public String getBridgeName() {
+        return bridgeName;
+    }
+
+    public void setBridgeName(String bridgeName) {
+        this.bridgeName = bridgeName;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java b/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java
index 05e81a1..c28d908 100644
--- a/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java
+++ b/plugins/network-elements/ovs/src/com/cloud/network/element/OvsElement.java
@@ -16,6 +16,8 @@
 // under the License.
 package com.cloud.network.element;
 
+import com.cloud.host.dao.HostDao;
+import com.cloud.vm.dao.UserVmDao;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -73,6 +75,8 @@ import com.cloud.vm.NicProfile;
 import com.cloud.vm.ReservationContext;
 import com.cloud.vm.VirtualMachineProfile;
 import com.cloud.vm.dao.DomainRouterDao;
+import com.cloud.vm.UserVmVO;
+import com.cloud.vm.VirtualMachine;
 
 @Local(value = {NetworkElement.class, ConnectivityProvider.class,
         SourceNatServiceProvider.class, StaticNatServiceProvider.class,
@@ -93,6 +97,10 @@ StaticNatServiceProvider, IpDeployer {
     DomainRouterDao _routerDao;
     @Inject
     VpcVirtualNetworkApplianceManager _routerMgr;
+    @Inject
+    UserVmDao _userVmDao;
+    @Inject
+    HostDao _hostDao;
 
     private static final Logger s_logger = Logger.getLogger(OvsElement.class);
     private static final Map<Service, Map<Capability, String>> capabilities = setCapabilities();
@@ -171,7 +179,12 @@ StaticNatServiceProvider, IpDeployer {
             return false;
         }
 
-        _ovsTunnelMgr.vmCheckAndCreateTunnel(vm, network, dest);
+        if (vm.getType() != VirtualMachine.Type.User && vm.getType() != VirtualMachine.Type.DomainRouter) {
+            return false;
+        }
+
+        // prepare the tunnel network on the host, in order for VM to get launched
+        _ovsTunnelMgr.checkAndPrepareHostForTunnelNetwork(network, dest.getHost());
 
         return true;
     }
@@ -192,7 +205,25 @@ StaticNatServiceProvider, IpDeployer {
             return false;
         }
 
-        _ovsTunnelMgr.checkAndDestroyTunnel(vm.getVirtualMachine(), network);
+        List<UserVmVO> userVms = _userVmDao.listByAccountIdAndHostId(vm.getVirtualMachine().getAccountId(),
+                vm.getVirtualMachine().getHostId());
+        if (vm.getType() == VirtualMachine.Type.User) {
+            if (userVms.size() > 1) {
+                return true;
+            }
+
+            List<DomainRouterVO> routers = _routerDao.findByNetwork(network.getId());
+            for (DomainRouterVO router : routers) {
+                if (router.getHostId().equals(vm.getVirtualMachine().getHostId())) {
+                    return true;
+                }
+            }
+        } else if (vm.getType() == VirtualMachine.Type.DomainRouter && userVms.size() != 0) {
+            return true;
+        }
+
+        HostVO host = _hostDao.findById(vm.getVirtualMachine().getHostId());
+        _ovsTunnelMgr.checkAndRemoveHostFromTunnelNetwork(network, host);
         return true;
     }
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java b/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java
index 8fa636d..2814c2a 100644
--- a/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java
+++ b/plugins/network-elements/ovs/src/com/cloud/network/guru/OvsGuestNetworkGuru.java
@@ -16,6 +16,8 @@
 // under the License.
 package com.cloud.network.guru;
 
+import com.cloud.network.vpc.VpcVO;
+import com.cloud.network.vpc.dao.VpcDao;
 import javax.ejb.Local;
 import javax.inject.Inject;
 
@@ -61,6 +63,8 @@ public class OvsGuestNetworkGuru extends GuestNetworkGuru {
     OvsTunnelManager _ovsTunnelMgr;
     @Inject
     NetworkOfferingServiceMapDao _ntwkOfferingSrvcDao;
+    @Inject
+    VpcDao _vpcDao;
 
     OvsGuestNetworkGuru() {
         super();
@@ -145,10 +149,14 @@ public class OvsGuestNetworkGuru extends GuestNetworkGuru {
             implemented.setCidr(network.getCidr());
         }
 
-        // do we need to create switch right now?
-
         implemented.setBroadcastDomainType(BroadcastDomainType.Vswitch);
 
+        if (network.getVpcId() != null && isVpcEnabledForDistributedRouter(network.getVpcId())) {
+            String keyStr = BroadcastDomainType.getValue(implemented.getBroadcastUri());
+            Long vpcid= network.getVpcId();
+            implemented.setBroadcastUri(BroadcastDomainType.Vswitch.toUri(vpcid.toString()+keyStr));
+        }
+
         return implemented;
     }
 
@@ -215,4 +223,9 @@ public class OvsGuestNetworkGuru extends GuestNetworkGuru {
             implemented.setBroadcastUri(network.getBroadcastUri());
         }
     }
+
+    boolean isVpcEnabledForDistributedRouter(long vpcId) {
+        VpcVO vpc = _vpcDao.findById(vpcId);
+        return vpc.usesDistributedRouter();
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsNetworkTopologyGuru.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsNetworkTopologyGuru.java b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsNetworkTopologyGuru.java
new file mode 100644
index 0000000..c410d10
--- /dev/null
+++ b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsNetworkTopologyGuru.java
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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 com.cloud.network.ovs;
+
+import com.cloud.utils.component.Manager;
+
+import java.util.List;
+
+public interface OvsNetworkTopologyGuru extends Manager {
+
+    /**
+     * get the list of hypervisor hosts id's on which VM's belonging to the network currently spans
+     */
+    public  List<Long> getNetworkSpanedHosts(long networkId);
+
+    /**
+     * get the list of hypervisor hosts id's on which VM's belonging to a VPC spans
+     */
+    public  List<Long> getVpcSpannedHosts(long vpId);
+
+    /**
+     * get the list of VPC id's of the vpc's for which one or more VM's from the VPC are running on the host
+     */
+    public  List<Long> getVpcOnHost(long hostId);
+
+    /**
+     * get the list of all active Vm id's in the VPC for all ther tiers
+     */
+    public List<Long> getAllActiveVmsInVpc(long vpcId);
+
+    /**
+     * get the list of all Vm id's in the VPC for all the tiers that are running on the host
+     */
+    public List<Long> getActiveVmsInVpcOnHost(long vpcId, long hostId);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsNetworkTopologyGuruImpl.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsNetworkTopologyGuruImpl.java b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsNetworkTopologyGuruImpl.java
new file mode 100644
index 0000000..7560e35
--- /dev/null
+++ b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsNetworkTopologyGuruImpl.java
@@ -0,0 +1,74 @@
+package com.cloud.network.ovs;
+
+import com.cloud.utils.component.ManagerBase;
+import com.cloud.vm.DomainRouterVO;
+import com.cloud.vm.UserVmVO;
+import com.cloud.vm.VMInstanceVO;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.dao.DomainRouterDao;
+import com.cloud.vm.dao.UserVmDao;
+import java.util.ArrayList;
+import java.util.List;
+import javax.ejb.Local;
+import javax.inject.Inject;
+import org.springframework.stereotype.Component;
+
+@Component
+@Local(value = {OvsNetworkTopologyGuru.class})
+public class OvsNetworkTopologyGuruImpl extends ManagerBase implements OvsNetworkTopologyGuru {
+
+    @Inject
+    UserVmDao _userVmDao;
+    @Inject
+    DomainRouterDao _routerDao;
+
+    /**
+     * get the list of hypervisor hosts on which VM's belonging to a network currently spans
+     */
+    public  List<Long> getNetworkSpanedHosts(long networkId) {
+        List<Long> hostIds = new ArrayList<Long>();
+        // Find active VMs with a NIC on the target network
+        List<UserVmVO> vms = _userVmDao.listByNetworkIdAndStates(networkId,
+                VirtualMachine.State.Running, VirtualMachine.State.Starting, VirtualMachine.State.Stopping, VirtualMachine.State.Unknown,
+                VirtualMachine.State.Migrating);
+        // Find routers for the network
+        List<DomainRouterVO> routers = _routerDao.findByNetwork(networkId);
+        List<VMInstanceVO> ins = new ArrayList<VMInstanceVO>();
+        if (vms != null) {
+            ins.addAll(vms);
+        }
+        if (routers.size() != 0) {
+            ins.addAll(routers);
+        }
+        for (VMInstanceVO v : ins) {
+            Long rh = v.getHostId();
+            if (rh == null) {
+                continue;
+            }
+            if (!hostIds.contains(rh)) {
+                hostIds.add(rh);
+            }
+        }
+        return  hostIds;
+    }
+
+    @Override
+    public List<Long> getVpcSpannedHosts(long vpId) {
+        return null;
+    }
+
+    @Override
+    public List<Long> getVpcOnHost(long hostId) {
+        return null;
+    }
+
+    @Override
+    public List<Long> getAllActiveVmsInVpc(long vpcId) {
+        return null;
+    }
+
+    @Override
+    public List<Long> getActiveVmsInVpcOnHost(long vpcId, long hostId) {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManager.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManager.java b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManager.java
index 118beeb..cd88136 100644
--- a/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManager.java
+++ b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManager.java
@@ -16,18 +16,24 @@
 // under the License.
 package com.cloud.network.ovs;
 
-import com.cloud.deploy.DeployDestination;
+import com.cloud.host.Host;
 import com.cloud.network.Network;
 import com.cloud.utils.component.Manager;
-import com.cloud.vm.VirtualMachine;
-import com.cloud.vm.VirtualMachineProfile;
 
 public interface OvsTunnelManager extends Manager {
 
     boolean isOvsTunnelEnabled();
 
-    public void vmCheckAndCreateTunnel(VirtualMachineProfile vm, Network nw, DeployDestination dest);
+    /**
+     *  create a bridge on the host if not already created for the network and establish full tunnel mesh with
+     *  the rest of the hosts on which network spans
+     */
+    public void checkAndPrepareHostForTunnelNetwork(Network nw, Host host);
 
-    public void checkAndDestroyTunnel(VirtualMachine vm, Network nw);
+    /**
+     * remove the bridge and tunnels to the hosts on which network spans if there are no other VM's
+     * belonging to the network are running on the host
+     */
+    public void checkAndRemoveHostFromTunnelNetwork(Network nw, Host host);
 
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java
index 320568b..ae37095 100644
--- a/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java
+++ b/plugins/network-elements/ovs/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java
@@ -16,6 +16,12 @@
 // under the License.
 package com.cloud.network.ovs;
 
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.vpc.VpcManager;
+import com.cloud.vm.Nic;
+import com.cloud.vm.NicVO;
+import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.dao.VMInstanceDao;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -42,9 +48,9 @@ import com.cloud.agent.api.OvsDestroyTunnelCommand;
 import com.cloud.agent.api.OvsFetchInterfaceAnswer;
 import com.cloud.agent.api.OvsFetchInterfaceCommand;
 import com.cloud.agent.api.OvsSetupBridgeCommand;
+import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand;
 import com.cloud.agent.manager.Commands;
 import com.cloud.configuration.Config;
-import com.cloud.deploy.DeployDestination;
 import com.cloud.exception.AgentUnavailableException;
 import com.cloud.exception.OperationTimedoutException;
 import com.cloud.host.Host;
@@ -60,19 +66,15 @@ import com.cloud.network.ovs.dao.OvsTunnelInterfaceDao;
 import com.cloud.network.ovs.dao.OvsTunnelInterfaceVO;
 import com.cloud.network.ovs.dao.OvsTunnelNetworkDao;
 import com.cloud.network.ovs.dao.OvsTunnelNetworkVO;
+import com.cloud.network.ovs.dao.OvsTunnel;
+import com.cloud.network.vpc.dao.VpcDao;
+import com.cloud.network.vpc.VpcVO;
 import com.cloud.utils.component.ManagerBase;
 import com.cloud.utils.concurrency.NamedThreadFactory;
 import com.cloud.utils.db.DB;
 import com.cloud.utils.exception.CloudRuntimeException;
-import com.cloud.vm.DomainRouterVO;
-import com.cloud.vm.UserVmVO;
-import com.cloud.vm.VMInstanceVO;
-import com.cloud.vm.VirtualMachine;
-import com.cloud.vm.VirtualMachine.State;
-import com.cloud.vm.VirtualMachineProfile;
 import com.cloud.vm.dao.DomainRouterDao;
 import com.cloud.vm.dao.NicDao;
-import com.cloud.vm.dao.UserVmDao;
 
 @Component
 @Local(value = {OvsTunnelManager.class})
@@ -91,8 +93,7 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
     HostDao _hostDao;
     @Inject
     PhysicalNetworkTrafficTypeDao _physNetTTDao;
-    @Inject
-    UserVmDao _userVmDao;
+
     @Inject
     DomainRouterDao _routerDao;
     @Inject
@@ -101,6 +102,16 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
     OvsTunnelInterfaceDao _tunnelInterfaceDao;
     @Inject
     AgentManager _agentMgr;
+    @Inject
+    OvsNetworkTopologyGuru _ovsNetworkToplogyGuru;
+    @Inject
+    VpcDao _vpcDao;
+    @Inject
+    VpcManager _vpcMgr;
+    @Inject
+    protected VMInstanceDao _vmInstanceDao;
+    @Inject
+    NetworkDao _networkDao;
 
     @Override
     public boolean configure(String name, Map<String, Object> params)
@@ -182,13 +193,13 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
                             from, to, networkId));
         }
         if (!r.getResult()) {
-            tunnel.setState("FAILED");
-            s_logger.warn("Create GRE tunnel failed due to " + r.getDetails()
+            tunnel.setState(OvsTunnel.State.Failed.name());
+            s_logger.warn("Create GRE tunnel from " + from + " to " + to + " failed due to " + r.getDetails()
                     + s);
         } else {
-            tunnel.setState("SUCCESS");
+            tunnel.setState(OvsTunnel.State.Established.name());
             tunnel.setPortName(r.getInPortName());
-            s_logger.warn("Create GRE tunnel " + r.getDetails() + s);
+            s_logger.info("Create GRE tunnel from " + from + " to " + to + " succeeded." + r.getDetails() + s);
         }
         _tunnelNetworkDao.update(tunnel.getId(), tunnel);
     }
@@ -249,13 +260,14 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
         int key = 0;
         try {
             //The GRE key is actually in the host part of the URI
-            // this is not true for lswitch/NiciraNvp!
             String keyStr = BroadcastDomainType.getValue(network.getBroadcastUri());
-            // The key is most certainly and int if network is a vlan.
-            // !! not in the case of lswitch/pvlan/(possibly)vswitch
-            // So we now feel quite safe in converting it into a string
-            // by calling the appropriate BroadcastDomainType method
-            key = Integer.parseInt(keyStr);
+            if (keyStr.contains(".")) {
+                String[] parts = keyStr.split(".");
+                key = Integer.parseInt(parts[1]);
+            } else {
+                key = Integer.parseInt(keyStr);
+            }
+
             return key;
         } catch (NumberFormatException e) {
             s_logger.debug("Well well, how did '" + key
@@ -268,41 +280,23 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
     }
 
     @DB
-    protected void checkAndCreateTunnel(VirtualMachine instance, Network nw, DeployDestination dest) {
+    protected void checkAndCreateTunnel(Network nw, Host host) {
 
         s_logger.debug("Creating tunnels with OVS tunnel manager");
-        if (instance.getType() != VirtualMachine.Type.User
-                && instance.getType() != VirtualMachine.Type.DomainRouter) {
-            s_logger.debug("Will not work if you're not"
-                    + "an instance or a virtual router");
-            return;
-        }
 
-        long hostId = dest.getHost().getId();
+        long hostId = host.getId();
         int key = getGreKey(nw);
-        // Find active VMs with a NIC on the target network
-        List<UserVmVO> vms = _userVmDao.listByNetworkIdAndStates(nw.getId(),
-                State.Running, State.Starting, State.Stopping, State.Unknown,
-                State.Migrating);
-        // Find routers for the network
-        List<DomainRouterVO> routers = _routerDao.findByNetwork(nw.getId());
-        List<VMInstanceVO> ins = new ArrayList<VMInstanceVO>();
-        if (vms != null) {
-            ins.addAll(vms);
-        }
-        if (routers.size() != 0) {
-            ins.addAll(routers);
-        }
+        String bridgeName = generateBridgeName(nw, key);
         List<Long> toHostIds = new ArrayList<Long>();
         List<Long> fromHostIds = new ArrayList<Long>();
-        for (VMInstanceVO v : ins) {
-            Long rh = v.getHostId();
-            if (rh == null || rh.longValue() == hostId) {
+        List<Long> networkSpannedHosts = _ovsNetworkToplogyGuru.getNetworkSpanedHosts(nw.getId());
+        for (Long rh : networkSpannedHosts) {
+            if (rh == hostId) {
                 continue;
             }
             OvsTunnelNetworkVO ta = _tunnelNetworkDao.getByFromToNetwork(hostId, rh.longValue(), nw.getId());
             // Try and create the tunnel even if a previous attempt failed
-            if (ta == null || ta.getState().equals("FAILED")) {
+            if (ta == null || ta.getState().equals(OvsTunnel.State.Failed.name())) {
                 s_logger.debug("Attempting to create tunnel from:" + hostId + " to:" + rh.longValue());
                 if (ta == null) {
                     createTunnelRecord(hostId, rh.longValue(), nw.getId(), key);
@@ -315,7 +309,7 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
             ta = _tunnelNetworkDao.getByFromToNetwork(rh.longValue(),
                     hostId, nw.getId());
             // Try and create the tunnel even if a previous attempt failed
-            if (ta == null || ta.getState().equals("FAILED")) {
+            if (ta == null || ta.getState().equals(OvsTunnel.State.Failed.name())) {
                 s_logger.debug("Attempting to create tunnel from:" +
                         rh.longValue() + " to:" + hostId);
                 if (ta == null) {
@@ -329,9 +323,9 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
         }
         //TODO: Should we propagate the exception here?
         try {
-            String myIp = getGreEndpointIP(dest.getHost(), nw);
+            String myIp = getGreEndpointIP(host, nw);
             if (myIp == null)
-                throw new GreTunnelException("Unable to retrieve the source " + "endpoint for the GRE tunnel." + "Failure is on host:" + dest.getHost().getId());
+                throw new GreTunnelException("Unable to retrieve the source " + "endpoint for the GRE tunnel." + "Failure is on host:" + host.getId());
             boolean noHost = true;
             for (Long i : toHostIds) {
                 HostVO rHost = _hostDao.findById(i);
@@ -343,7 +337,8 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
                                     + "Failure is on host:" + rHost.getId());
                 Commands cmds = new Commands(
                         new OvsCreateTunnelCommand(otherIp, key,
-                                Long.valueOf(hostId), i, nw.getId(), myIp));
+                                Long.valueOf(hostId), i, nw.getId(), myIp, bridgeName, nw.getUuid()));
+                s_logger.debug("Attempting to create tunnel from:" + hostId + " to:" + i + " for the network " + nw.getId());
                 s_logger.debug("Ask host " + hostId
                         + " to create gre tunnel to " + i);
                 Answer[] answers = _agentMgr.send(hostId, cmds);
@@ -355,21 +350,19 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
                 HostVO rHost = _hostDao.findById(i);
                 String otherIp = getGreEndpointIP(rHost, nw);
                 Commands cmds = new Commands(new OvsCreateTunnelCommand(myIp,
-                        key, i, Long.valueOf(hostId), nw.getId(), otherIp));
+                        key, i, Long.valueOf(hostId), nw.getId(), otherIp, bridgeName, nw.getUuid()));
                 s_logger.debug("Ask host " + i + " to create gre tunnel to "
                         + hostId);
                 Answer[] answers = _agentMgr.send(i, cmds);
                 handleCreateTunnelAnswer(answers);
                 noHost = false;
             }
+
             // If no tunnels have been configured, perform the bridge setup
-            // anyway
-            // This will ensure VIF rules will be triggered
+            // anyway. This will ensure VIF rules will be triggered
             if (noHost) {
-                Commands cmds = new Commands(new OvsSetupBridgeCommand(key,
-                        hostId, nw.getId()));
-                s_logger.debug("Ask host " + hostId
-                        + " to configure bridge for network:" + nw.getId());
+                Commands cmds = new Commands(new OvsSetupBridgeCommand(bridgeName, hostId, nw.getId()));
+                s_logger.debug("Ask host " + hostId + " to configure bridge for network:" + nw.getId());
                 Answer[] answers = _agentMgr.send(hostId, cmds);
                 handleSetupBridgeAnswer(answers);
             }
@@ -384,10 +377,20 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
         return true;
     }
 
+    boolean isVpcEnabledForDistributedRouter(long vpcId) {
+        VpcVO vpc = _vpcDao.findById(vpcId);
+        return vpc.usesDistributedRouter();
+    }
+
     @Override
-    public void vmCheckAndCreateTunnel(VirtualMachineProfile vm,
-            Network nw, DeployDestination dest) {
-        checkAndCreateTunnel(vm.getVirtualMachine(), nw, dest);
+    public void checkAndPrepareHostForTunnelNetwork(Network nw, Host host) {
+        if (nw.getVpcId() != null && isVpcEnabledForDistributedRouter(nw.getVpcId())) {
+            // check and setup host to be in full tunnel mesh with each of the network in the VPC
+            checkAndCreateVpcTunnelNetworks(host, nw.getVpcId());
+        } else {
+            // check and setup host to be in full tunnel mesh with the network
+            checkAndCreateTunnel(nw, host);
+        }
     }
 
     @DB
@@ -440,45 +443,28 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
     }
 
     @Override
-    public void checkAndDestroyTunnel(VirtualMachine vm, Network nw) {
-        // if (!_isEnabled) {
-        // return;
-        // }
-
-        List<UserVmVO> userVms = _userVmDao.listByAccountIdAndHostId(vm.getAccountId(), vm.getHostId());
-        if (vm.getType() == VirtualMachine.Type.User) {
-            if (userVms.size() > 1) {
-                return;
-            }
+    public void checkAndRemoveHostFromTunnelNetwork(Network nw, Host host) {
 
-            List<DomainRouterVO> routers = _routerDao.findByNetwork(nw.getId());
-            for (DomainRouterVO router : routers) {
-                if (router.getHostId().equals(vm.getHostId())) {
-                    return;
-                }
-            }
-        } else if (vm.getType() == VirtualMachine.Type.DomainRouter && userVms.size() != 0) {
-            return;
-        }
         try {
             /* Now we are last one on host, destroy the bridge with all
              * the tunnels for this network  */
             int key = getGreKey(nw);
-            Command cmd = new OvsDestroyBridgeCommand(nw.getId(), key);
-            s_logger.debug("Destroying bridge for network " + nw.getId() + " on host:" + vm.getHostId());
-            Answer ans = _agentMgr.send(vm.getHostId(), cmd);
-            handleDestroyBridgeAnswer(ans, vm.getHostId(), nw.getId());
+            String bridgeName = generateBridgeName(nw, key);
+            Command cmd = new OvsDestroyBridgeCommand(nw.getId(), bridgeName);
+            s_logger.debug("Destroying bridge for network " + nw.getId() + " on host:" + host.getId());
+            Answer ans = _agentMgr.send(host.getId(), cmd);
+            handleDestroyBridgeAnswer(ans, host.getId(), nw.getId());
 
             /* Then ask hosts have peer tunnel with me to destroy them */
             List<OvsTunnelNetworkVO> peers =
-                    _tunnelNetworkDao.listByToNetwork(vm.getHostId(),
+                    _tunnelNetworkDao.listByToNetwork(host.getId(),
                             nw.getId());
             for (OvsTunnelNetworkVO p : peers) {
                 // If the tunnel was not successfully created don't bother to remove it
-                if (p.getState().equals("SUCCESS")) {
-                    cmd = new OvsDestroyTunnelCommand(p.getNetworkId(), key,
+                if (p.getState().equals(OvsTunnel.State.Established.name())) {
+                    cmd = new OvsDestroyTunnelCommand(p.getNetworkId(), bridgeName,
                             p.getPortName());
-                    s_logger.debug("Destroying tunnel to " + vm.getHostId() +
+                    s_logger.debug("Destroying tunnel to " + host.getId() +
                             " from " + p.getFrom());
                     ans = _agentMgr.send(p.getFrom(), cmd);
                     handleDestroyTunnelAnswer(ans, p.getFrom(),
@@ -486,8 +472,204 @@ public class OvsTunnelManagerImpl extends ManagerBase implements OvsTunnelManage
                 }
             }
         } catch (Exception e) {
-            s_logger.warn(String.format("Destroy tunnel(account:%1$s," + "hostId:%2$s) failed", vm.getAccountId(), vm.getHostId()), e);
+            s_logger.warn(String.format("Destroy tunnel failed", e));
+        }
+    }
+
+    private String generateBridgeName(Network nw, int key) {
+        if (nw.getVpcId() != null && isVpcEnabledForDistributedRouter(nw.getVpcId())) {
+            return "OVS-DR-VPC-Bridge" + nw.getVpcId();
+        } else {
+            return "OVSTunnel"+key;
+        }
+    }
+    private String generateBridgeNameForVpc(long vpcId) {
+        return "OVS-DR-VPC-Bridge" + vpcId;
+    }
+
+    public boolean sendVpcTopologyChangeUpdate(OvsVpcPhysicalTopologyConfigCommand updateCmd, long hostId, String bridgeName) {
+        try {
+            s_logger.debug("Sending VPC topology update to the host " + hostId);
+            updateCmd.setHostId(hostId);
+            updateCmd.setBridgeName(bridgeName);
+            Answer ans = _agentMgr.send(hostId, updateCmd);
+            if (ans.getResult()) {
+                s_logger.debug("Successfully updated the host " + hostId + " with latest VPC topology." );
+                return true;
+            }  else {
+                s_logger.debug("Failed to update the host " + hostId + " with latest VPC topology." );
+                return false;
+            }
+        } catch (Exception e) {
+            s_logger.debug("Failed to updated the host " + hostId + " with latest VPC topology." );
+            return false;
         }
     }
 
+    OvsVpcPhysicalTopologyConfigCommand prepareVpcTopologyUpdate(long vpcId) {
+        VpcVO vpc = _vpcDao.findById(vpcId);
+        assert (vpc != null): "invalid vpc id";
+
+        List<? extends Network> vpcNetworks =  _vpcMgr.getVpcNetworks(vpcId);
+        List<Long> hostIds = _ovsNetworkToplogyGuru.getVpcSpannedHosts(vpcId);
+        List<Long> vmIds = _ovsNetworkToplogyGuru.getAllActiveVmsInVpc(vpcId);
+
+        List<OvsVpcPhysicalTopologyConfigCommand.Host> hosts = new ArrayList<OvsVpcPhysicalTopologyConfigCommand.Host>();
+        List<OvsVpcPhysicalTopologyConfigCommand.Tier> tiers = new ArrayList<OvsVpcPhysicalTopologyConfigCommand.Tier>();
+        List<OvsVpcPhysicalTopologyConfigCommand.Vm> vms = new ArrayList<OvsVpcPhysicalTopologyConfigCommand.Vm>();
+
+        for (Long hostId : hostIds) {
+            HostVO hostDetails = _hostDao.findById(hostId);
+            String remoteIp = null;
+            for (Network network: vpcNetworks) {
+                try {
+                    remoteIp = getGreEndpointIP(hostDetails, network);
+                } catch (Exception e) {
+
+                }
+            }
+            OvsVpcPhysicalTopologyConfigCommand.Host host = new OvsVpcPhysicalTopologyConfigCommand.Host(hostId, remoteIp);
+            hosts.add(host);
+        }
+
+        for (Network network: vpcNetworks) {
+            String key = BroadcastDomainType.getValue(network.getBroadcastUri());
+            long gre_key;
+            if (key.contains(".")) {
+                String[] parts = key.split(".");
+                gre_key = Long.parseLong(parts[1]);
+            } else {
+                try {
+                    gre_key = Long.parseLong(BroadcastDomainType.getValue(key));
+                } catch (Exception e) {
+                    return null;
+                }
+            }
+            NicVO nic = _nicDao.findByIp4AddressAndNetworkId(network.getGateway(), network.getId());
+            OvsVpcPhysicalTopologyConfigCommand.Tier tier = new OvsVpcPhysicalTopologyConfigCommand.Tier(gre_key,
+                    network.getUuid(), network.getGateway(), nic.getMacAddress(), network.getCidr());
+            tiers.add(tier);
+        }
+
+        for (long vmId: vmIds) {
+            VirtualMachine vmInstance = _vmInstanceDao.findById(vmId);
+            List<OvsVpcPhysicalTopologyConfigCommand.Nic>  vmNics = new ArrayList<OvsVpcPhysicalTopologyConfigCommand.Nic>();
+            for (Nic vmNic :_nicDao.listByVmId(vmId)) {
+                Network network = _networkDao.findById(vmNic.getNetworkId());
+                if (network.getTrafficType() == TrafficType.Guest) {
+                    OvsVpcPhysicalTopologyConfigCommand.Nic nic =  new OvsVpcPhysicalTopologyConfigCommand.Nic(
+                            vmNic.getIp4Address(), vmNic.getMacAddress(), ((Long)vmNic.getNetworkId()).toString());
+                    vmNics.add(nic);
+                }
+            }
+            OvsVpcPhysicalTopologyConfigCommand.Vm vm = new OvsVpcPhysicalTopologyConfigCommand.Vm(
+                    vmInstance.getHostId(), vmNics.toArray(new OvsVpcPhysicalTopologyConfigCommand.Nic[vmNics.size()]));
+            vms.add(vm);
+        }
+        return new OvsVpcPhysicalTopologyConfigCommand(
+                hosts.toArray(new OvsVpcPhysicalTopologyConfigCommand.Host[hosts.size()]),
+                tiers.toArray(new OvsVpcPhysicalTopologyConfigCommand.Tier[tiers.size()]),
+                vms.toArray(new OvsVpcPhysicalTopologyConfigCommand.Vm[vms.size()]),
+                vpc.getCidr());
+    }
+
+    @DB
+    protected void checkAndCreateVpcTunnelNetworks(Host host, long vpcId) {
+
+        long hostId = host.getId();
+        List<? extends Network> vpcNetworks =  _vpcMgr.getVpcNetworks(vpcId);
+        List<Long> vpcSpannedHostIds = _ovsNetworkToplogyGuru.getVpcSpannedHosts(vpcId);
+        String bridgeName=generateBridgeNameForVpc(vpcId);
+
+        for (Network vpcNetwork: vpcNetworks) {
+            int key = getGreKey(vpcNetwork);
+            List<Long> toHostIds = new ArrayList<Long>();
+            List<Long> fromHostIds = new ArrayList<Long>();
+
+            for (Long rh : vpcSpannedHostIds) {
+                if (rh == hostId) {
+                    continue;
+                }
+                OvsTunnelNetworkVO ta = _tunnelNetworkDao.getByFromToNetwork(hostId, rh.longValue(), vpcNetwork.getId());
+                // Try and create the tunnel even if a previous attempt failed
+                if (ta == null || ta.getState().equals(OvsTunnel.State.Failed.name())) {
+                    s_logger.debug("Attempting to create tunnel from:" + hostId + " to:" + rh.longValue());
+                    if (ta == null) {
+                        createTunnelRecord(hostId, rh.longValue(), vpcNetwork.getId(), key);
+                    }
+                    if (!toHostIds.contains(rh)) {
+                        toHostIds.add(rh);
+                    }
+                }
+
+                ta = _tunnelNetworkDao.getByFromToNetwork(rh.longValue(),
+                        hostId, vpcNetwork.getId());
+                // Try and create the tunnel even if a previous attempt failed
+                if (ta == null || ta.getState().equals(OvsTunnel.State.Failed.name())) {
+                    s_logger.debug("Attempting to create tunnel from:" +
+                            rh.longValue() + " to:" + hostId);
+                    if (ta == null) {
+                        createTunnelRecord(rh.longValue(), hostId,
+                                vpcNetwork.getId(), key);
+                    }
+                    if (!fromHostIds.contains(rh)) {
+                        fromHostIds.add(rh);
+                    }
+                }
+            }
+
+            try {
+                String myIp = getGreEndpointIP(host, vpcNetwork);
+                if (myIp == null)
+                    throw new GreTunnelException("Unable to retrieve the source " + "endpoint for the GRE tunnel."
+                            + "Failure is on host:" + host.getId());
+                boolean noHost = true;
+
+                for (Long i : toHostIds) {
+                    HostVO rHost = _hostDao.findById(i);
+                    String otherIp = getGreEndpointIP(rHost, vpcNetwork);
+                    if (otherIp == null)
+                        throw new GreTunnelException(
+                                "Unable to retrieve the remote "
+                                        + "endpoint for the GRE tunnel."
+                                        + "Failure is on host:" + rHost.getId());
+                    Commands cmds = new Commands(
+                            new OvsCreateTunnelCommand(otherIp, key,
+                                    Long.valueOf(hostId), i, vpcNetwork.getId(), myIp, bridgeName,
+                                    vpcNetwork.getUuid()));
+                    s_logger.debug("Attempting to create tunnel from:" + hostId + " to:" + i + " for the network "
+                            + vpcNetwork.getId());
+                    s_logger.debug("Ask host " + hostId
+                            + " to create gre tunnel to " + i);
+                    Answer[] answers = _agentMgr.send(hostId, cmds);
+                    handleCreateTunnelAnswer(answers);
+                    noHost = false;
+                }
+
+                for (Long i : fromHostIds) {
+                    HostVO rHost = _hostDao.findById(i);
+                    String otherIp = getGreEndpointIP(rHost, vpcNetwork);
+                    Commands cmds = new Commands(new OvsCreateTunnelCommand(myIp,
+                            key, i, Long.valueOf(hostId), vpcNetwork.getId(), otherIp, bridgeName,
+                            vpcNetwork.getUuid()));
+                    s_logger.debug("Ask host " + i + " to create gre tunnel to "
+                            + hostId);
+                    Answer[] answers = _agentMgr.send(i, cmds);
+                    handleCreateTunnelAnswer(answers);
+                    noHost = false;
+                }
+            } catch (GreTunnelException | OperationTimedoutException | AgentUnavailableException e) {
+                // I really thing we should do a better handling of these exceptions
+                s_logger.warn("Ovs Tunnel network created tunnel failed", e);
+            }
+        }
+
+        OvsVpcPhysicalTopologyConfigCommand topologyConfigCommand = prepareVpcTopologyUpdate(vpcId);
+        for (Long id: vpcSpannedHostIds) {
+            if (!sendVpcTopologyChangeUpdate(topologyConfigCommand, id, bridgeName)) {
+                s_logger.debug("Failed to send VPC topology change update to host : " + id + ". Moving on with rest of" +
+                        "the host update.");
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/plugins/network-elements/ovs/src/com/cloud/network/ovs/dao/OvsTunnel.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/ovs/src/com/cloud/network/ovs/dao/OvsTunnel.java b/plugins/network-elements/ovs/src/com/cloud/network/ovs/dao/OvsTunnel.java
new file mode 100644
index 0000000..3216ac7
--- /dev/null
+++ b/plugins/network-elements/ovs/src/com/cloud/network/ovs/dao/OvsTunnel.java
@@ -0,0 +1,24 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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 com.cloud.network.ovs.dao;
+
+public interface OvsTunnel {
+    public enum State {
+        Created, Established, Failed
+    }
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/plugins/network-elements/ovs/src/com/cloud/network/ovs/dao/OvsTunnelNetworkVO.java
----------------------------------------------------------------------
diff --git a/plugins/network-elements/ovs/src/com/cloud/network/ovs/dao/OvsTunnelNetworkVO.java b/plugins/network-elements/ovs/src/com/cloud/network/ovs/dao/OvsTunnelNetworkVO.java
index 2826912..88a7591 100644
--- a/plugins/network-elements/ovs/src/com/cloud/network/ovs/dao/OvsTunnelNetworkVO.java
+++ b/plugins/network-elements/ovs/src/com/cloud/network/ovs/dao/OvsTunnelNetworkVO.java
@@ -62,7 +62,7 @@ public class OvsTunnelNetworkVO implements InternalIdentity {
         this.key = key;
         this.networkId = networkId;
         this.portName = "[]";
-        this.state = "FAILED";
+        this.state = OvsTunnel.State.Created.name();
     }
 
     public void setKey(int key) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/scripts/vm/hypervisor/xenserver/ovstunnel
----------------------------------------------------------------------
diff --git a/scripts/vm/hypervisor/xenserver/ovstunnel b/scripts/vm/hypervisor/xenserver/ovstunnel
index d558e97..64a2d36 100755
--- a/scripts/vm/hypervisor/xenserver/ovstunnel
+++ b/scripts/vm/hypervisor/xenserver/ovstunnel
@@ -224,6 +224,7 @@ def create_tunnel(session, args):
     gre_key = args.pop("key")
     src_host = args.pop("from")
     dst_host = args.pop("to")
+    network_uuid = args.pop("cloudstack-network-id")
 
     logging.debug("Entering create_tunnel")
 
@@ -318,6 +319,7 @@ def create_tunnel(session, args):
 
             # add flow rule to send the traffic from tunnel ports to L2 switching table only
             lib.add_flow(bridge, priority=1000, in_port=tun_ofport, table=0, actions='resubmit(,1)')
+            lib.do_cmd([lib.VSCTL_PATH, "set", "interface", name, "options:cloudstack-network-id=%s" % network_uuid])
 
         return "SUCCESS:%s" % name
     except:

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/8dcce6aa/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
index 4af20c6..b643ec4 100644
--- a/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
+++ b/server/src/com/cloud/hypervisor/HypervisorGuruBase.java
@@ -16,6 +16,7 @@
 // under the License.
 package com.cloud.hypervisor;
 
+import com.cloud.network.dao.NetworkVO;
 import java.util.List;
 import java.util.Map;
 
@@ -41,6 +42,7 @@ import com.cloud.vm.VMInstanceVO;
 import com.cloud.vm.VirtualMachine;
 import com.cloud.vm.VirtualMachineProfile;
 import com.cloud.vm.dao.NicDao;
+import com.cloud.network.dao.NetworkDao;
 import com.cloud.vm.dao.NicSecondaryIpDao;
 import com.cloud.vm.dao.UserVmDetailsDao;
 import com.cloud.vm.dao.VMInstanceDao;
@@ -52,6 +54,8 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
     @Inject
     NicDao _nicDao;
     @Inject
+    NetworkDao  _networkDao;
+    @Inject
     VMInstanceDao _virtualMachineDao;
     @Inject
     UserVmDetailsDao _userVmDetailsDao;
@@ -87,6 +91,9 @@ public abstract class HypervisorGuruBase extends AdapterBase implements Hypervis
         to.setName(profile.getName());
         to.setSecurityGroupEnabled(profile.isSecurityGroupEnabled());
 
+        NetworkVO network = _networkDao.findById(profile.getNetworkId());
+        to.setNetworkUuid(network.getUuid());
+
         // Workaround to make sure the TO has the UUID we need for Niciri integration
         NicVO nicVO = _nicDao.findById(profile.getId());
         to.setUuid(nicVO.getUuid());