diff --git a/api/src/com/cloud/network/ovs/OvsCreateTunnelCommand.java b/api/src/com/cloud/network/ovs/OvsCreateTunnelCommand.java index 454723dfc34..df16618f21e 100644 --- a/api/src/com/cloud/network/ovs/OvsCreateTunnelCommand.java +++ b/api/src/com/cloud/network/ovs/OvsCreateTunnelCommand.java @@ -15,7 +15,7 @@ package com.cloud.network.ovs; import com.cloud.agent.api.Command; public class OvsCreateTunnelCommand extends Command { - String key; + Integer key; String remoteIp; Long from; Long to; @@ -29,7 +29,7 @@ public class OvsCreateTunnelCommand extends Command { return true; } - public OvsCreateTunnelCommand(String remoteIp, String key, Long from, Long to, long networkId, String fromIp) { + public OvsCreateTunnelCommand(String remoteIp, Integer key, Long from, Long to, long networkId, String fromIp) { this.remoteIp = remoteIp; this.key = key; this.from = from; @@ -38,7 +38,7 @@ public class OvsCreateTunnelCommand extends Command { this.fromIp = fromIp; } - public String getKey() { + public Integer getKey() { return key; } diff --git a/api/src/com/cloud/network/ovs/OvsSetupBridgeCommand.java b/api/src/com/cloud/network/ovs/OvsSetupBridgeCommand.java new file mode 100644 index 00000000000..4cf2d36dc5d --- /dev/null +++ b/api/src/com/cloud/network/ovs/OvsSetupBridgeCommand.java @@ -0,0 +1,51 @@ +/** + * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. + * + * This software is licensed under the GNU General Public License v3 or later. + * + * It is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.cloud.network.ovs; + +import com.cloud.agent.api.Command; + +public class OvsSetupBridgeCommand extends Command { + Integer key; + Long hostId; + Long networkId; + + @Override + public boolean executeInSequence() { + return true; + } + + public OvsSetupBridgeCommand(Integer key, Long hostId, Long networkId) { + this.key = key; + this.hostId = hostId; + this.networkId = networkId; + } + + public Integer getKey() { + return key; + } + + public Long getHostId() { + return hostId; + } + + public Long getNetworkId() { + return networkId; + } + +} diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index 6194fa697b3..3c5cb6041b8 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -181,6 +181,7 @@ import com.cloud.network.ovs.OvsDestroyBridgeCommand; import com.cloud.network.ovs.OvsDestroyTunnelCommand; import com.cloud.network.ovs.OvsSetTagAndFlowAnswer; import com.cloud.network.ovs.OvsSetTagAndFlowCommand; +import com.cloud.network.ovs.OvsSetupBridgeCommand; import com.cloud.resource.ServerResource; import com.cloud.resource.hypervisor.HypervisorResource; import com.cloud.storage.Storage; @@ -617,7 +618,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe /** * This method just creates a XenServer network following the tunnel network naming convention */ - private synchronized Network createTunnelNetwork(Connection conn, long networkId) { + private synchronized Network findOrCreateTunnelNetwork(Connection conn, long networkId) { try { String nwName = "OVSTunnel" + networkId; Network nw = null; @@ -632,11 +633,13 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe otherConfig.put("ovs-host-setup", ""); rec.otherConfig = otherConfig; nw = Network.create(conn, rec); + // Plug dom0 vif only when creating network + enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + networkId); + s_logger.debug("### Xen Server network for tunnels created:" + nwName); } else { nw = networks.iterator().next(); + s_logger.debug("### Xen Server network for tunnels found:" + nwName); } - enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + networkId); - s_logger.debug("### Xen Server network for tunnels created:" + nwName); return nw; } catch (Exception e) { s_logger.warn("createTunnelNetwork failed", e); @@ -647,9 +650,9 @@ 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 createAndConfigureTunnelNetwork(Connection conn, long networkId, long hostId) { + private synchronized Network configureTunnelNetwork(Connection conn, long networkId, long hostId, int key) { try { - Network nw = createTunnelNetwork(conn, networkId); + Network nw = findOrCreateTunnelNetwork(conn, networkId); //Invoke plugin to setup the bridge which will be used by this network String bridge = nw.getBridge(conn); Map nwOtherConfig = nw.getOtherConfig(conn); @@ -666,7 +669,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } if (!configured) { String result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge", "bridge", bridge, - "key", String.valueOf(networkId), + "key", String.valueOf(key), "xs_nw_uuid", nw.getUuid(conn), "cs_host_id", ((Long)hostId).toString()); //Note down the fact that the ovs bridge has been setup @@ -684,29 +687,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe } } - private synchronized Network findTunnelNetwork(Connection conn, long networkId) { - try { - String nwName = "OVSTunnel" + networkId; - Network nw = null; - Set networks = Network.getByNameLabel(conn, nwName); - if (networks.size() == 0) { - String errorMessage = "Unable to find OVS bridge for network:" + networkId; - s_logger.error(errorMessage); - throw new CloudRuntimeException(errorMessage); - } else { - nw = networks.iterator().next(); - } - s_logger.debug("### Xen Server network for tunnels found:" + nwName); - return nw; - } catch (Exception e) { - s_logger.warn("findTunnelNetwork failed:", e); - return null; - } - } - private synchronized void destroyTunnelNetwork(Connection conn, long networkId) { try { - Network nw = findTunnelNetwork(conn, networkId); + Network nw = findOrCreateTunnelNetwork(conn, networkId); String bridge = nw.getBridge(conn); String result = callHostPlugin(conn, "ovstunnel", "destroy_ovs_bridge", "bridge", bridge); String[] res = result.split(":"); @@ -747,7 +730,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return setupvSwitchNetwork(conn); } else { long networkId = Long.parseLong(nic.getBroadcastUri().getHost()); - return createTunnelNetwork(conn, networkId); + return findOrCreateTunnelNetwork(conn, networkId); } } else if (nic.getBroadcastType() == BroadcastDomainType.Storage) { URI broadcastUri = nic.getBroadcastUri(); @@ -4802,6 +4785,16 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe return Boolean.valueOf(callHostPlugin(conn, "vmops", "can_bridge_firewall", "host_uuid", _host.uuid, "instance", _instance)); } + + private Answer execute(OvsSetupBridgeCommand cmd) { + Connection conn = getConnection(); + s_logger.debug("### About to configure OVS bridge"); + Network nw=findOrCreateTunnelNetwork(conn, cmd.getNetworkId()); + this.configureTunnelNetwork(conn, cmd.getNetworkId(), cmd.getHostId(), cmd.getKey()); + s_logger.debug("### Bridge configured"); + return new Answer(cmd, true, null); + } + private Answer execute(OvsDestroyBridgeCommand cmd) { Connection conn = getConnection(); s_logger.debug("### About to destroy OVS bridge"); @@ -4814,7 +4807,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe Connection conn = getConnection(); s_logger.debug("### About to destroy tunnel network"); try { - Network nw = findTunnelNetwork(conn, cmd.getNetworkId()); + Network nw = findOrCreateTunnelNetwork(conn, cmd.getNetworkId()); if (nw == null) { s_logger.warn("### Unable to find tunnel network"); return new Answer(cmd, false, "No network found"); @@ -4846,16 +4839,17 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe String bridge = "unknown"; try { s_logger.debug("### About to create tunnel network"); - Network nw = createAndConfigureTunnelNetwork(conn, cmd.getNetworkId(), cmd.getFrom()); + Network nw = findOrCreateTunnelNetwork(conn, cmd.getNetworkId()); if (nw == null) { s_logger.debug("### SOMETHING WENT WRONG DURING NETWORK SETUP"); return new OvsCreateTunnelAnswer(cmd, false, "Cannot create network", bridge); } - + + configureTunnelNetwork(conn, cmd.getNetworkId(), cmd.getFrom(), cmd.getKey()); bridge = nw.getBridge(conn); s_logger.debug("### The bridge is:" + bridge); - String result = callHostPlugin(conn, "ovstunnel", "create_tunnel", "bridge", bridge, "remote_ip", cmd.getRemoteIp(), "key", cmd.getKey(), "from", cmd.getFrom().toString(), "to", cmd - .getTo().toString()); + 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()); s_logger.debug("### Result from create tunnel operation:" + result); String[] res = result.split(":"); if (res.length == 2 && res[0].equalsIgnoreCase("SUCCESS")) { diff --git a/scripts/vm/hypervisor/xenserver/ovstunnel b/scripts/vm/hypervisor/xenserver/ovstunnel index 6e0ff1f8c76..d900477d928 100755 --- a/scripts/vm/hypervisor/xenserver/ovstunnel +++ b/scripts/vm/hypervisor/xenserver/ovstunnel @@ -155,9 +155,8 @@ def setup_ovs_bridge(session, args): version_cmd = [lib.XE_PATH, 'host-param-get', 'uuid=%s' % host_uuid, 'param-name=software-version', 'param-key=product_version'] - version = lib.do_cmd(version_cmd) + version = lib.do_cmd(version_cmd).split('.')[0] block_ipv6_handlers[version](bridge) - lib.add_flow(bridge, priority=65000, proto='ipv6', actions='drop') logging.debug("Setup_ovs_bridge completed with result:%s" %result) return result diff --git a/scripts/vm/hypervisor/xenserver/xenserver56fp1/ovs-vif-flows.py b/scripts/vm/hypervisor/xenserver/xenserver56fp1/ovs-vif-flows.py index 937c892224c..e2d7b423f4e 100644 --- a/scripts/vm/hypervisor/xenserver/xenserver56fp1/ovs-vif-flows.py +++ b/scripts/vm/hypervisor/xenserver/xenserver56fp1/ovs-vif-flows.py @@ -77,15 +77,12 @@ def main(command, vif_raw): if this_vif == vif: this_vif_ofport = vif_ofport vif_ofports.append(vif_ofport) - # So regardless of whether the VIF is brought online or offline we - # will always execute the same action - if command == 'offline': - clear_flows(bridge, this_vif_ofport, vif_ofports) - if command == 'online': - apply_flows(bridge, this_vif_ofport, vif_ofports) - - + if command == 'offline': + clear_flows(bridge, this_vif_ofport, vif_ofports) + + if command == 'online': + apply_flows(bridge, this_vif_ofport, vif_ofports) if __name__ == "__main__": @@ -95,4 +92,4 @@ if __name__ == "__main__": sys.exit(1) else: command, vif_raw = sys.argv[1:3] - main(command, vif_raw) \ No newline at end of file + main(command, vif_raw) diff --git a/server/src/com/cloud/network/NetworkManagerImpl.java b/server/src/com/cloud/network/NetworkManagerImpl.java index fb6d6bdb185..49b4d30bed6 100755 --- a/server/src/com/cloud/network/NetworkManagerImpl.java +++ b/server/src/com/cloud/network/NetworkManagerImpl.java @@ -4827,15 +4827,18 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag // for GRE phynets allow up to 32bits // TODO: Not happy about this test. // What about guru-like objects for physical networs? + s_logger.debug("ISOLATION METHODS:" + network.getIsolationMethods()); + // Java does not have unsigned types... if (network.getIsolationMethods().contains("GRE")) { - maxVnet = 2^32 - 1; + maxVnet = (int)(Math.pow(2, 32)-1); } + String rangeMessage = " between 0 and " + maxVnet; if (newVnetRange.length < 2) { - throw new InvalidParameterValueException("Please provide valid vnet range between 0-4096"); + throw new InvalidParameterValueException("Please provide valid vnet range" + rangeMessage); } if (newVnetRange[0] == null || newVnetRange[1] == null) { - throw new InvalidParameterValueException("Please provide valid vnet range between 0-4096"); + throw new InvalidParameterValueException("Please provide valid vnet range" + rangeMessage); } try { @@ -4843,14 +4846,14 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag newEndVnet = Integer.parseInt(newVnetRange[1]); } catch (NumberFormatException e) { s_logger.warn("Unable to parse vnet range:", e); - throw new InvalidParameterValueException("Please provide valid vnet range between 0-4096"); + throw new InvalidParameterValueException("Please provide valid vnet range" + rangeMessage); } if (newStartVnet < 0 || newEndVnet > maxVnet) { - throw new InvalidParameterValueException("Vnet range has to be between 0-4096"); + throw new InvalidParameterValueException("Vnet range has to be" + rangeMessage); } if (newStartVnet > newEndVnet) { - throw new InvalidParameterValueException("Vnet range has to be between 0-4096 and start range should be lesser than or equal to stop range"); + throw new InvalidParameterValueException("Vnet range has to be" + rangeMessage + " and start range should be lesser than or equal to stop range"); } if (physicalNetworkHasAllocatedVnets(network.getDataCenterId(), network.getId())) { diff --git a/server/src/com/cloud/network/guru/OvsGuestNetworkGuru.java b/server/src/com/cloud/network/guru/OvsGuestNetworkGuru.java index 8babbbc9582..15b6ea0663f 100644 --- a/server/src/com/cloud/network/guru/OvsGuestNetworkGuru.java +++ b/server/src/com/cloud/network/guru/OvsGuestNetworkGuru.java @@ -73,7 +73,14 @@ public class OvsGuestNetworkGuru extends GuestNetworkGuru { if (vnet == null) { throw new InsufficientVirtualNetworkCapcityException("Unable to allocate vnet as a part of network " + network + " implement ", DataCenter.class, dcId); } - implemented.setBroadcastUri(BroadcastDomainType.Vswitch.toUri(vnet)); + String vnetUri = null; + if (_ovsNetworkMgr.isOvsNetworkEnabled()) { + vnetUri = "vlan" + vnet; + } else if (_ovsTunnelMgr.isOvsTunnelEnabled()) { + vnetUri = vnet; + } + implemented.setBroadcastUri(BroadcastDomainType.Vswitch.toUri(vnetUri)); + s_logger.debug("### URI value:" + vnetUri); EventUtils.saveEvent(UserContext.current().getCallerUserId(), network.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ZONE_VLAN_ASSIGN, "Assigned Zone Vlan: "+vnet+ " Network Id: "+network.getId(), 0); } else { implemented.setBroadcastUri(network.getBroadcastUri()); @@ -89,15 +96,6 @@ public class OvsGuestNetworkGuru extends GuestNetworkGuru { s_logger.debug("### Implementing network:" + config.getId() + " in OVS Guest Network Guru"); // The above call will NOT reserve a Vnet NetworkVO implemented = (NetworkVO)super.implement(config, offering, dest, context); - String uri = null; - if (_ovsNetworkMgr.isOvsNetworkEnabled()) { - uri = "vlan"; - } else if (_ovsTunnelMgr.isOvsTunnelEnabled()) { - uri = Long.toString(config.getId()); - } - s_logger.debug("### URI value:" + uri); - implemented.setBroadcastUri(BroadcastDomainType.Vswitch.toUri(uri)); - s_logger.debug("### Broadcast URI is:" + implemented.getBroadcastUri().toString()); return implemented; } diff --git a/server/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java b/server/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java index 40883ea7220..f01184f67cf 100644 --- a/server/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java +++ b/server/src/com/cloud/network/ovs/OvsTunnelManagerImpl.java @@ -85,6 +85,7 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager { return true; } + @DB protected OvsTunnelNetworkVO createTunnelRecord(long from, long to, long networkId, int key) { OvsTunnelNetworkVO ta = null; @@ -200,24 +201,36 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager { try { String myIp = dest.getHost().getPrivateIpAddress(); + boolean noHost = true; for (Long i : toHostIds) { HostVO rHost = _hostDao.findById(i); Commands cmds = new Commands( - new OvsCreateTunnelCommand(rHost.getPrivateIpAddress(), String.valueOf(nw.getId()), - Long.valueOf(hostId), i, nw.getId(), myIp)); + new OvsCreateTunnelCommand(rHost.getPrivateIpAddress(), key, + Long.valueOf(hostId), i, nw.getId(), myIp)); 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); - Commands cmd2s = new Commands( - new OvsCreateTunnelCommand(myIp, String.valueOf(nw.getId()), - i, Long.valueOf(hostId), nw.getId(), rHost.getPrivateIpAddress())); + Commands cmds = new Commands( + new OvsCreateTunnelCommand(myIp, key, i, Long.valueOf(hostId), + nw.getId(), rHost.getPrivateIpAddress())); s_logger.debug("Ask host " + i + " to create gre tunnel to " + hostId); - Answer[] answers = _agentMgr.send(i, cmd2s); + Answer[] answers = _agentMgr.send(i, cmds); handleCreateTunnelAnswer(answers); + noHost = false; + } + // If not tunnels have been configured, perform the bridge setup 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()); + Answer[] answers = _agentMgr.send(hostId, cmds); + handleSetupBridgeAnswer(answers); } } catch (Exception e) { s_logger.warn("Ovs Tunnel network created tunnel failed", e); @@ -249,6 +262,7 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager { CheckAndCreateTunnel(vm.getVirtualMachine(), nw, dest); } + @DB private void handleDestroyTunnelAnswer(Answer ans, long from, long to, long network_id) { if (ans.getResult()) { @@ -271,6 +285,7 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager { } } + @DB private void handleDestroyBridgeAnswer(Answer ans, long host_id, long network_id) { if (ans.getResult()) { @@ -289,6 +304,11 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager { } } + private void handleSetupBridgeAnswer(Answer[] answers) { + //TODO: Add some error management here? + s_logger.debug("Placeholder for something more meanginful to come"); + } + @Override public void CheckAndDestroyTunnel(VirtualMachine vm, Network nw) { s_logger.debug("### DESTROYING YOUR TUNNELS!");