From 8987499cdaa74bcaa2b5fbda4d0c769a1ac3ad60 Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Fri, 16 Mar 2012 13:55:53 +0000 Subject: [PATCH] Now using vnets instead of network id for creating networks Fixed issues with vif scripts on 5.6FP1 Fixed ipv6 issue on 5.6FP1 Plus other various fixes and improvements Starting to remove debug code NOTE: Network is configured correctly but instances do not start. Possibly indefinite wait occuring on some commands --- .../network/ovs/OvsCreateTunnelCommand.java | 6 +- .../network/ovs/OvsSetupBridgeCommand.java | 51 ++++++++++++++++ .../xen/resource/CitrixResourceBase.java | 60 +++++++++---------- scripts/vm/hypervisor/xenserver/ovstunnel | 3 +- .../xenserver/xenserver56fp1/ovs-vif-flows.py | 15 ++--- .../com/cloud/network/NetworkManagerImpl.java | 15 +++-- .../network/guru/OvsGuestNetworkGuru.java | 18 +++--- .../network/ovs/OvsTunnelManagerImpl.java | 32 ++++++++-- 8 files changed, 131 insertions(+), 69 deletions(-) create mode 100644 api/src/com/cloud/network/ovs/OvsSetupBridgeCommand.java 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!");