diff --git a/api/src/com/cloud/network/ovs/OvsSetTagAndFlowCommand.java b/api/src/com/cloud/network/ovs/OvsSetTagAndFlowCommand.java index c74f9c13e1f..6ff8934a7ae 100644 --- a/api/src/com/cloud/network/ovs/OvsSetTagAndFlowCommand.java +++ b/api/src/com/cloud/network/ovs/OvsSetTagAndFlowCommand.java @@ -6,6 +6,7 @@ public class OvsSetTagAndFlowCommand extends Command { String vlans; String vmName; String seqno; + String tag; Long vmId; @Override @@ -29,8 +30,13 @@ public class OvsSetTagAndFlowCommand extends Command { return vmId; } - public OvsSetTagAndFlowCommand(String vmName, String vlans, String seqno, Long vmId) { + public String getTag() { + return tag; + } + + public OvsSetTagAndFlowCommand(String vmName, String tag, String vlans, String seqno, Long vmId) { this.vmName = vmName; + this.tag = tag; this.vlans = vlans; this.seqno = seqno; this.vmId = vmId; diff --git a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index e607e4a08e9..536fc1b0eac 100644 --- a/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/core/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -3835,9 +3835,7 @@ public abstract class CitrixResourceBase implements ServerResource { Connection conn = getConnection(); try { - String nwName = Networks.BroadcastScheme.VSwitch.toString(); - Network nw = getNetworkByName(conn, nwName); - assert nw!= null : "Why there is no vswith network ???"; + Network nw = setupvSwitchNetwork(conn); String bridge = nw.getBridge(conn); String result = callHostPlugin(conn, "vmops", "ovs_delete_flow", "bridge", bridge, "vmName", cmd.getVmName()); @@ -3861,12 +3859,12 @@ public abstract class CitrixResourceBase implements ServerResource { List> states = new ArrayList>(); for (String log: logs){ String [] info = log.split(","); - if (info.length != 4) { + if (info.length != 5) { s_logger.warn("Wrong element number in ovs log"); continue; } - //','.join([bridge, vmName, vmId, seqno]) + //','.join([bridge, vmName, vmId, seqno, tag]) try { states.add(new Pair(info[0], Long.parseLong(info[3]))); } catch (NumberFormatException nfe) { @@ -3887,9 +3885,7 @@ public abstract class CitrixResourceBase implements ServerResource { Connection conn = getConnection(); try { - String nwName = Networks.BroadcastScheme.VSwitch.toString(); - Network nw = getNetworkByName(conn, nwName); - assert nw!= null : "Why there is no vswith network ???"; + Network nw = setupvSwitchNetwork(conn); String bridge = nw.getBridge(conn); /*If VM is domainRouter, this will try to set flow and tag on its @@ -3897,7 +3893,8 @@ public abstract class CitrixResourceBase implements ServerResource { * plugin side */ String result = callHostPlugin(conn, "vmops", "ovs_set_tag_and_flow", "bridge", bridge, - "vmName", cmd.getVmName(), "vlans", cmd.getVlans(), "seqno", cmd.getSeqNo()); + "vmName", cmd.getVmName(), "tag", cmd.getTag(), + "vlans", cmd.getVlans(), "seqno", cmd.getSeqNo()); s_logger.debug("set flow for " + cmd.getVmName() + " " + result); if (result.equalsIgnoreCase("SUCCESS")) { diff --git a/scripts/vm/hypervisor/xenserver/vlanRemapUtils.py b/scripts/vm/hypervisor/xenserver/vlanRemapUtils.py index 58850aef5a4..2b0a804a04e 100644 --- a/scripts/vm/hypervisor/xenserver/vlanRemapUtils.py +++ b/scripts/vm/hypervisor/xenserver/vlanRemapUtils.py @@ -17,7 +17,7 @@ vSwitchPidFile = "/var/run/openvswitch/ovs-vswitchd.pid" vsctlPath = "/usr/bin/ovs-vsctl" vSwitchDaemonName = "ovs-vswitchd" -logFile = "/var/log/cloud/management/vlanRemapUtils.log" +logFile = "/var/log/vlanRemapUtils.log" fLog = None global result @@ -256,7 +256,7 @@ def getVifPort(bridge, vifName): portUuids = getPortsOnBridge(bridge) if portUuids == None: log("No ports on bridge %s" % bridge) - return -1 + return None for i in portUuids: name = getFieldOfPort(i, "name") @@ -335,7 +335,17 @@ def delARPFlow(vlan): doCmd(delFlow) def delDHCPFlow(vlan): - param = "dl_type=0x0800 nw_proto=6 tp_src=547 dl_vlan=%s" % vlan + param = "dl_type=0x0800 nw_proto=17 tp_dst=68 dl_vlan=%s" % vlan + delFlow = ["ovs-ofctl del-flows %s" % bridge, '"%s"' % param] + doCmd(delFlow) + +def delDHCPClientFlow(vlan): + param = "dl_type=0x0800 nw_proto=17 tp_dst=67 dl_vlan=%s" % vlan + delFlow = ["ovs-ofctl del-flows %s" % bridge, '"%s"' % param] + doCmd(delFlow) + +def delDropFlow(vlan): + param = "priority=0 dl_vlan=%s" % vlan delFlow = ["ovs-ofctl del-flows %s" % bridge, '"%s"' % param] doCmd(delFlow) @@ -345,7 +355,17 @@ def formatDHCPFlow(bridge, inPort, vlan, ports): str = "output:%s," % i outputs += str outputs = outputs[:-1] - flow = "in_port=%s dl_vlan=%s dl_type=0x0800 nw_proto=6 tp_src=547 idle_timeout=0 hard_timeout=0 \ + flow = "in_port=%s dl_vlan=%s dl_type=0x0800 nw_proto=17 tp_dst=67 idle_timeout=0 hard_timeout=0 \ + priority=10000 actions=strip_vlan,%s" % (inPort, vlan, outputs) + return flow + +def formatDHCPClientFlow(bridge, inPort, vlan, ports): + outputs = '' + for i in ports: + str = "output:%s," % i + outputs += str + outputs = outputs[:-1] + flow = "in_port=%s dl_vlan=%s dl_type=0x0800 nw_proto=17 tp_dst=68 idle_timeout=0 hard_timeout=0 \ priority=10000 actions=strip_vlan,%s" % (inPort, vlan, outputs) return flow @@ -378,12 +398,7 @@ def createFlow (bridge, vifName, mac, remap): result = errors["NO_OFPORT"] return -1 - #del old flow here, if any, but in normal there should be no old flow - #maybe we need add check here - delFlow(mac) - #set remap here, remap has format e.g. [1,22,200,13,16] - remap = strip(remap) log("") log("Create flow for remap") noneGreOfPorts = getNoneGreOfPort(bridge) @@ -393,8 +408,6 @@ def createFlow (bridge, vifName, mac, remap): isARP = False for j in remap.split("/"): - delARPFlow(j) - delDHCPFlow(j) for i in inport: flow = formatDropFlow(i, j) param = bridge + ' "%s"' % flow @@ -418,6 +431,11 @@ def createFlow (bridge, vifName, mac, remap): addflow = ["ovs-ofctl add-flow", param] doCmd (addflow) + flow = formatDHCPClientFlow(bridge, i, j, noneGreOfPorts) + param = bridge + ' "%s"' % flow + addflow = ["ovs-ofctl add-flow", param] + doCmd (addflow) + result = errors["SUCCESS"] return 0 ######################## End Flow creation utils ########################## @@ -463,30 +481,63 @@ remap=%s" % (bridge, vifName, mac, remap)) def doSetTag (bridge, vifName, tag): setTag(bridge, vifName, tag) -def doDeleteFlow(bridge, vifName, mac, remap): - delFlow(mac) - log("Delete flows for %s" % mac) +def doAskPorts(bridge, vifNames): + vifs = vifNames.split(",") + if len(vifs) == 0: + return ' ' + + ofports = [] + for vif in vifs: + op = getVifPort(bridge, vif) + if op == None: + log("doAskPorts: no port(bridge:%s, vif:%s)" % (bridge, vif)) + continue + ofports.append(op) + + return ",".join(ofports) + +def doDeleteFlow(bridge, ofports, macs, remap): + for i in macs.split(","): + delFlow(i) + log("Delete flows for %s" % i) remap = strip(remap) # remove our port from arp flow inport = getGreOfPorts(bridge) if len(inport) == 0: + log("WARNING:no inports") return - mine = getVifPort(bridge, vifName) noneGreOfPorts = getNoneGreOfPort(bridge) - noneGreOfPorts.remove(mine) - log("Delete ARP flows for(vifname=%s, ofport=%s)" % (vifName, mine)) + for i in ofports.split(","): + try: + noneGreOfPorts.remove(i) + except: + log("WARNING:ofport %s is not on bridge %s" % (i, bridge)) + log("Delete ARP flows for(ofport=%s)" % i) for j in remap.split("/"): delARPFlow(j) + delDHCPFlow(j) + delDHCPClientFlow(j) + delDropFlow(j) for i in inport: flow = formatARPFlow(bridge, i, j, noneGreOfPorts) param = bridge + ' "%s"' % flow addflow = ["ovs-ofctl add-flow", param] doCmd (addflow) + flow = formatDHCPFlow(bridge, i, j, noneGreOfPorts) + param = bridge + ' "%s"' % flow + addflow = ["ovs-ofctl add-flow", param] + doCmd (addflow) + + flow = formatDHCPClientFlow(bridge, i, j, noneGreOfPorts) + param = bridge + ' "%s"' % flow + addflow = ["ovs-ofctl add-flow", param] + doCmd (addflow) + def checkArgNum(num): if len (sys.argv) < num: result = errors["ERR_ARGS_NUM"] @@ -524,16 +575,22 @@ if __name__ == "__main__": elif op == "deleteFlow": checkArgNum(6) bridge = sys.argv[2] - vifName = sys.argv[3] - mac = sys.argv[4] + ofports = sys.argv[3] + macs = sys.argv[4] remap = sys.argv[5] - doDeleteFlow(bridge, vifName, mac, remap) + doDeleteFlow(bridge, ofports, macs, remap) elif op == "setTag": checkArgNum(5) bridge = sys.argv[2] vifName = sys.argv[3] tag = sys.argv[4] doSetTag(bridge, vifName, tag) + elif op == "askPorts": + checkArgNum(4) + bridge = sys.argv[2] + vifNames = sys.argv[3] + print doAskPorts(bridge, vifNames) + sys.exit(0) else: log("WARNING: get an unkown op %s" % op) result=errors["ERROR_OP"] diff --git a/scripts/vm/hypervisor/xenserver/vmops b/scripts/vm/hypervisor/xenserver/vmops index fb6f9a2194b..0b827af411b 100755 --- a/scripts/vm/hypervisor/xenserver/vmops +++ b/scripts/vm/hypervisor/xenserver/vmops @@ -147,13 +147,17 @@ def vlanRemapUtils(session, args): cmd.insert(7, args.pop("remap")) elif op == "deleteFlow": cmd.insert(3, args.pop("bridge")) - cmd.insert(4, args.pop("vifName")) - cmd.insert(5, args.pop("mac")) + cmd.insert(4, args.pop("ofports")) + cmd.insert(5, args.pop("macs")) cmd.insert(6, args.pop("remap")) elif op == "setTag": cmd.insert(3, args.pop("bridge")) cmd.insert(4, args.pop("vifName")) cmd.insert(5, args.pop("tag")) + elif op == "askPorts": + cmd.insert(3, args.pop("bridge")) + cmd.insert(4, args.pop("vifNames")) + try: txt = util.pread2(cmd) @@ -592,6 +596,9 @@ def ovs_get_mac_info_from_log(vmName): def ovs_get_vlans_info_from_log(vmName): return ovs_get_info_from_log(vmName, 3) +def ovs_get_ofports_info_from_log(vmName): + return ovs_get_info_from_log(vmName, 4) + def ovs_parse_common_info_from_log(vmName, num): info = ovs_get_common_info_from_log(vmName) if info == None: @@ -607,6 +614,10 @@ def ovs_get_vm_id_from_log(vmName): def ovs_get_seqno_from_log(vmName): return ovs_parse_common_info_from_log(vmName, 3) +def ovs_get_tag_from_log(vmName): + return ovs_parse_common_info_from_log(vmName, 4) + + def ovs_handle_rebooted_vm(session, vmName): curr_domid = '-1' @@ -619,7 +630,7 @@ def ovs_handle_rebooted_vm(session, vmName): util.SMlog("%s rebooted, reset flow for it" % vmName) try: - vlans = ovs_get_vlans_info_from_log(vmName) + vlanstr = ovs_get_vlans_info_from_log(vmName) bridge = ovs_get_bridge_from_log(vmName) except Exception, e: util.SMlog(e.__str__()) @@ -628,22 +639,23 @@ def ovs_handle_rebooted_vm(session, vmName): return False i = 0 - if vlans == None: - util.SMlog("OVSErr: cannot get vlans for %s" % vmName) + if vlanstr == None: + util.SMlog("OVSErr: cannot get vlanstr for %s" % vmName) return False - tag = vlans.split('/')[0] + tag = ovs_get_tag_from_log(vmName) nics = [] macs = [] for vifr in vifrs: vifName = "vif" + curr_domid + "." + vifr[0] vlanRemapUtils(session, {"op":"setTag", "vifName":vifName, "bridge":bridge, "tag":tag}) - vlanRemapUtils(session, {"op":"createFlow", "vifName":vifName, "bridge":bridge, "mac":vifr[1], "remap":vlans}) + vlanRemapUtils(session, {"op":"createFlow", "vifName":vifName, "bridge":bridge, "mac":vifr[1], "remap":vlanstr}) nics.append(vifName) macs.append(vifr[1]) i += 1 seqno = ovs_get_seqno_from_log(vmName) - ovs_write_vm_log(bridge, vmName, curr_domid, seqno, nics, macs, vlans) + ofports = ovs_get_ofports_info_from_log(vmName) + ovs_write_vm_log(bridge, vmName, curr_domid, seqno, nics, macs, tag, vlanstr, ofports) #see if there is rebooted vm to handle ovs_get_vm_log(session, {"host_uuid":hostuuid}) @@ -677,12 +689,12 @@ def ovs_get_vm_log(session, args): return ";".join(result) -def ovs_write_vm_log(bridge, vmName, vmId, seqno, vifNames, macs, vlans): +def ovs_write_vm_log(bridge, vmName, vmId, seqno, vifNames, macs, tag, vlans, ofports): logfilename = format_ovs_vm_log_name(vmName) util.SMlog("Writing ovs log to " + logfilename) logf = open(logfilename, 'w') - output = ','.join([vmName, bridge, vmId, seqno]) + output = ','.join([vmName, bridge, vmId, seqno, tag]) result = True try: logf.write(output) @@ -695,6 +707,8 @@ def ovs_write_vm_log(bridge, vmName, vmId, seqno, vifNames, macs, vlans): logf.write('\n') logf.write(vlans) logf.write('\n') + logf.write(ofports) + logf.write('\n') except: util.SMlog("Failed to write to ovs log file " + logfilename) result = False @@ -707,23 +721,17 @@ def ovs_delete_flow(session, args): bridge = args.pop('bridge') vm_name = args.pop('vmName') - nicStr = ovs_get_nic_info_from_log(vm_name) - macStr = ovs_get_mac_info_from_log(vm_name) - vlanStr = ovs_get_vlans_info_from_log(vm_name) + macs = ovs_get_mac_info_from_log(vm_name) + vlans = ovs_get_vlans_info_from_log(vm_name) + ofports = ovs_get_ofports_info_from_log(vm_name) - if nicStr == None or macStr == None or vlanStr == None: + if macs == None or vlans == None or ofports == None: return 'ERROR_LOG' - nics = nicStr.split(',') - macs = macStr.split(',') - if len(nics) != len(macs): - return 'ERROR_LOG' + vlanRemapUtils(session, {"op":"deleteFlow", "bridge":bridge, \ + "ofports":ofports, "macs":macs, "remap":vlans}) - i = 0 - for nic in nics: - vlanRemapUtils(session, {"op":"deleteFlow", "bridge":bridge, \ - "vifName":nic, "mac":macs[i], "remap":vlanStr}) - i += 1 + remove_ovs_log_for_vm(vm_name) return 'SUCCESS' def ovs_get_domid_vifrs_hostuuid(session, vm_name): @@ -755,6 +763,7 @@ def ovs_set_tag_and_flow(session, args): bridge = args.pop('bridge') vm_name = args.pop('vmName') vlanStr = args.pop('vlans') + tag = args.pop('tag') seqno = args.pop('seqno') (domid, vifrs, hostuuid) = ovs_get_domid_vifrs_hostuuid(session, vm_name) @@ -766,6 +775,9 @@ def ovs_set_tag_and_flow(session, args): if len(vifrs) == 0: return 'SUCCESS' + #delete old flows first + ovs_delete_flow(session, {"bridge":bridge, "vmName":vm_name}) + if vlanStr.startswith("/"): vlanStr = vlanStr[1:] if vlanStr.endswith("/"): vlanStr = vlanStr[:-1] vlans = vlanStr.split("/") @@ -776,10 +788,11 @@ def ovs_set_tag_and_flow(session, args): vifNames.append(vifName) mac = vifr[1] macs.append(mac) - vlanRemapUtils(session, {"op":"setTag", "vifName":vifName, "bridge":bridge, "tag":vlans[0]}) + vlanRemapUtils(session, {"op":"setTag", "vifName":vifName, "bridge":bridge, "tag":tag}) vlanRemapUtils(session, {"op":"createFlow", "vifName":vifName, "bridge":bridge, "mac":mac, "remap":vlanStr}) - res = ovs_write_vm_log(bridge, vm_name, domid, seqno, vifNames, macs, vlanStr) + ofports = vlanRemapUtils(session, {"op":"askPorts", "bridge":bridge, "vifNames":",".join(vifNames)}) + res = ovs_write_vm_log(bridge, vm_name, domid, seqno, vifNames, macs, tag, vlanStr, ofports) if res == 'false': return 'CREATE_LOG_FAILED' diff --git a/server/src/com/cloud/network/element/OvsElement.java b/server/src/com/cloud/network/element/OvsElement.java index f1e5c5683c9..53495fbaca4 100644 --- a/server/src/com/cloud/network/element/OvsElement.java +++ b/server/src/com/cloud/network/element/OvsElement.java @@ -15,6 +15,7 @@ import com.cloud.network.PublicIpAddress; import com.cloud.network.Network.Capability; import com.cloud.network.Network.Provider; import com.cloud.network.Network.Service; +import com.cloud.network.Networks.BroadcastDomainType; import com.cloud.network.ovs.OvsNetworkManager; import com.cloud.network.rules.FirewallRule; import com.cloud.offering.NetworkOffering; @@ -58,13 +59,12 @@ public class OvsElement extends AdapterBase implements NetworkElement { InsufficientCapacityException { VirtualMachine instance = vm.getVirtualMachine(); - if (instance.getType() == VirtualMachine.Type.DomainRouter) { + if (network.getTrafficType() != Networks.TrafficType.Guest || + instance.getType() == VirtualMachine.Type.DomainRouter) { return true; - } + } - if (network.getTrafficType() == Networks.TrafficType.Guest) { - _ovsNetworkMgr.CheckAndUpdateDhcpFlow(network, vm.getVirtualMachine()); - } + //_ovsNetworkMgr.CheckAndUpdateDhcpFlow(network, vm.getVirtualMachine()); return true; } diff --git a/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java b/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java index 029a275cb51..fab01a77639 100644 --- a/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java +++ b/server/src/com/cloud/network/ovs/OvsNetworkManagerImpl.java @@ -195,6 +195,8 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { } String vlans = getVlanMapping(vm.getAccountId()); + String tag = Long.toString(_vlanMappingDao.findByAccountIdAndHostId( + vm.getAccountId(), vm.getHostId()).getVlan()); Long agentId = null; VmFlowLogVO log = _flowLogDao.findByVmId(userVmId); if (log == null) { @@ -207,7 +209,7 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { agentId = vm.getHostId(); if (agentId != null ) { OvsSetTagAndFlowCommand cmd = new OvsSetTagAndFlowCommand( - vm.getName(), vlans, seqnum.toString(), vm.getId()); + vm.getName(), tag, vlans, seqnum.toString(), vm.getId()); Commands cmds = new Commands(cmd); try { _agentMgr.send(agentId, cmds, _ovsListener); @@ -273,8 +275,11 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { VlanMappingVO newVlan = new VlanMappingVO(accountId, hostId, vlan); _vlanMappingDao.persist(newVlan); _vlanMappingDirtyDao.markDirty(accountId); + String s = String.format("allocate a new vlan %1$s(account:%2$s, hostId:%3$s), mark dirty", + vlan, accountId, hostId); + s_logger.debug("OVSDIRTY:" + s); txn.commit(); - return 0; + return vlan; } @Override @@ -294,8 +299,8 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { assert vlans.size() > 0 : "Vlan map can't be null"; StringBuffer buf = new StringBuffer(); + buf.append("/"); for (Long i : vlans) { - buf.append("/"); buf.append(i.toString()); buf.append("/"); } @@ -345,16 +350,10 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { _agentMgr.send(i.longValue(), cmd2s , _ovsListener); s_logger.debug("Ask host " + i.longValue() + " to create gre tunnel to " + hostId); } - _vlanMappingDirtyDao.markDirty(accountId); } catch (Exception e) { e.printStackTrace(); } } - - private String parseVlanAndMapping(String uri) { - String sub = uri.substring(BroadcastDomainType.Vswitch.scheme().length() + "://".length() - 1); - return sub; - } protected void applyDefaultFlow(Commands cmds, VMInstanceVO instance, DeployDestination dest) { @@ -368,28 +367,43 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { return; } - List nics = _nicDao.listBy(instance.getId()); - if (nics.size() == 0) + String tag = Long.toString(askVlanId(instance.getAccountId(), instance.getHostId())); + String vlans = getVlanMapping(instance.getAccountId()); + CheckAndUpdateDhcpFlow(instance); + VmFlowLogVO log = _flowLogDao.findOrNewByVmId(instance.getId(), instance.getName()); + cmds.addCommand(new OvsSetTagAndFlowCommand(instance.getName(), tag, vlans, + Long.toString(log.getLogsequence()), instance.getId())); + } + + //FIXME: if router has record in database but not start, this will hang 10 secs due to host + //plugin cannot found vif for router. + public void CheckAndUpdateDhcpFlow(VMInstanceVO instance) { + if (!_isEnabled) { return; - - NicVO nic = null; - if (vmType == VirtualMachine.Type.DomainRouter) { - for (NicVO n : nics) { - NetworkVO network = _networkDao.findById(n.getNetworkId()); - if (network.getTrafficType() == TrafficType.Guest) { - nic = n; - break; - } - } - } else { - nic = nics.get(0); } - assert nic!=null : "Why there is no guest network nic???"; - String vlans = parseVlanAndMapping(nic.getBroadcastUri().toASCIIString()); - VmFlowLogVO log = _flowLogDao.findOrNewByVmId(instance.getId(), instance.getName()); - cmds.addCommand(new OvsSetTagAndFlowCommand(instance.getName(), vlans, - Long.toString(log.getLogsequence()), instance.getId())); + long accountId = instance.getAccountId(); + DomainRouterVO router = _routerDao.findBy(accountId, instance.getDataCenterId()); + if (router == null) { + return; + } + + if (!_vlanMappingDirtyDao.isDirty(accountId)) { + return; + } + + try { + String vlans = getVlanMapping(accountId); + String tag = Long.toString(_vlanMappingDao.findByAccountIdAndHostId(router.getAccountId(), + router.getHostId()).getVlan()); + VmFlowLogVO log = _flowLogDao.findOrNewByVmId(instance.getId(), instance.getName()); + _agentMgr.send(router.getHostId(), new OvsSetTagAndFlowCommand( + router.getName(), tag, vlans, Long.toString(log.getLogsequence()), instance.getId())); + s_logger.debug("ask router " + router.getName() + " on host " + + router.getHostId() + " update vlan map to " + vlans); + } catch (Exception e) { + e.printStackTrace(); + } } //FIXME: if at this router is not start, this will hang 10 secs due to host @@ -412,9 +426,11 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { try { String vlans = getVlanMapping(accountId); + String tag = Long.toString(_vlanMappingDao.findByAccountIdAndHostId(router.getAccountId(), + router.getHostId()).getVlan()); VmFlowLogVO log = _flowLogDao.findOrNewByVmId(vm.getId(), vm.getName()); _agentMgr.send(router.getHostId(), new OvsSetTagAndFlowCommand( - router.getName(), vlans, Long.toString(log.getLogsequence()), vm.getId())); + router.getName(), tag, vlans, Long.toString(log.getLogsequence()), vm.getId())); s_logger.debug("ask router " + router.getName() + " on host " + router.getHostId() + " update vlan map to " + vlans); } catch (Exception e) { @@ -479,6 +495,7 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { protected Set getAffectedVms(VMInstanceVO instance) { long accountId = instance.getAccountId(); if (!_vlanMappingDirtyDao.isDirty(accountId)) { + s_logger.debug("OVSAFFECTED: no VM affected by " + instance.getName()); return null; } @@ -487,6 +504,13 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { for (UserVmVO vm : vms) { affectedVms.add(new Long(vm.getId())); } + + if (instance.getType() != VirtualMachine.Type.DomainRouter) { + DomainRouterVO router = _routerDao.findBy(accountId, instance.getDataCenterId()); + if (router != null) { + affectedVms.add(new Long(router.getId())); + } + } return affectedVms; } @@ -494,7 +518,7 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { Set affectedVms = getAffectedVms(instance); scheduleFlowUpdateToHosts(affectedVms, true, null); _vlanMappingDirtyDao.clean(instance.getAccountId()); - s_logger.debug("Clean dirty for account " + instance.getAccountId()); + s_logger.debug("OVSDIRTY:Clean dirty for account " + instance.getAccountId()); } //TODO: think about lock @@ -508,10 +532,10 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager { VlanMappingVO vo = _vlanMappingDao.findByAccountIdAndHostId(accountId, hostId); if (vo.unref() == 0) { _vlanMappingDao.remove(vo.getId()); - s_logger.debug(instance.getName() + " is the last one on host " - + hostId + " for account " + accountId - + ", remove vlan in ovs_host_vlan_alloc"); _vlanMappingDirtyDao.markDirty(accountId); + String s = String.format("%1$s is the last VM(host:%2$s, accountId:%3$s), remove vlan", + instance.getName(), hostId, accountId); + s_logger.debug("OVSDIRTY:" + s); } else { _vlanMappingDao.update(vo.getId(), vo); s_logger.debug(instance.getName() diff --git a/server/src/com/cloud/network/ovs/dao/VlanMappingDaoImpl.java b/server/src/com/cloud/network/ovs/dao/VlanMappingDaoImpl.java index ea801138125..14cb19c1628 100644 --- a/server/src/com/cloud/network/ovs/dao/VlanMappingDaoImpl.java +++ b/server/src/com/cloud/network/ovs/dao/VlanMappingDaoImpl.java @@ -12,21 +12,30 @@ import javax.ejb.Local; @Local(value = { VlanMappingDao.class }) public class VlanMappingDaoImpl extends GenericDaoBase implements VlanMappingDao { - protected final SearchBuilder AllFieldsSearch; + protected final SearchBuilder accountIdSearch; + protected final SearchBuilder hostSearch; + protected final SearchBuilder accountHostSearch; public VlanMappingDaoImpl() { super(); - AllFieldsSearch = createSearchBuilder(); - AllFieldsSearch.and("host_id", AllFieldsSearch.entity().getHostId(), Op.EQ); - AllFieldsSearch.and("account_id", AllFieldsSearch.entity().getAccountId(), Op.EQ); - AllFieldsSearch.and("vlan", AllFieldsSearch.entity().getAccountId(), Op.EQ); - AllFieldsSearch.done(); + accountHostSearch = createSearchBuilder(); + accountHostSearch.and("host_id", accountHostSearch.entity().getHostId(), Op.EQ); + accountHostSearch.and("account_id", accountHostSearch.entity().getAccountId(), Op.EQ); + accountHostSearch.done(); + + accountIdSearch = createSearchBuilder(); + accountIdSearch.and("account_id", accountIdSearch.entity().getAccountId(), Op.EQ); + accountIdSearch.done(); + + hostSearch = createSearchBuilder(); + hostSearch.and("host_id", hostSearch.entity().getHostId(), Op.EQ); + hostSearch.done(); } @Override public List listByAccountIdAndHostId(long accountId, long hostId) { - SearchCriteria sc = AllFieldsSearch.create(); + SearchCriteria sc = accountHostSearch.create(); sc.setParameters("account_id", accountId); sc.setParameters("host_id", hostId); return listBy(sc, null); @@ -34,7 +43,7 @@ public class VlanMappingDaoImpl extends GenericDaoBase @Override public List listByHostId(long hostId) { - SearchCriteria sc = AllFieldsSearch.create(); + SearchCriteria sc = hostSearch.create(); sc.setParameters("host_id", hostId); return listBy(sc, null); @@ -42,7 +51,7 @@ public class VlanMappingDaoImpl extends GenericDaoBase @Override public List listByAccountId(long accountId) { - SearchCriteria sc = AllFieldsSearch.create(); + SearchCriteria sc = accountIdSearch.create(); sc.setParameters("account_id", accountId); return listBy(sc, null); @@ -50,8 +59,9 @@ public class VlanMappingDaoImpl extends GenericDaoBase @Override public VlanMappingVO findByAccountIdAndHostId(long accountId, long hostId) { - SearchCriteria sc = AllFieldsSearch.create(); + SearchCriteria sc = accountHostSearch.create(); sc.setParameters("account_id", accountId); + sc.setParameters("host_id", hostId); return findOneBy(sc); } } diff --git a/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyDaoImpl.java b/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyDaoImpl.java index f2f54cb80e5..fb6739b7cda 100644 --- a/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyDaoImpl.java +++ b/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyDaoImpl.java @@ -10,19 +10,18 @@ import com.cloud.utils.db.SearchCriteria.Op; @Local(value = { VlanMappingDirtyDao.class }) public class VlanMappingDirtyDaoImpl extends GenericDaoBase implements VlanMappingDirtyDao { - protected final SearchBuilder AllFieldsSearch; + protected final SearchBuilder AccountIdSearch; public VlanMappingDirtyDaoImpl() { super(); - AllFieldsSearch = createSearchBuilder(); - AllFieldsSearch.and("account_id", AllFieldsSearch.entity().getAccountId(), Op.EQ); - AllFieldsSearch.and("dirty", AllFieldsSearch.entity().isDirty(), Op.EQ); - AllFieldsSearch.done(); + AccountIdSearch = createSearchBuilder(); + AccountIdSearch.and("account_id", AccountIdSearch.entity().getAccountId(), Op.EQ); + AccountIdSearch.done(); } @Override public boolean isDirty(long accountId) { - SearchCriteria sc = AllFieldsSearch.create(); + SearchCriteria sc = AccountIdSearch.create(); sc.setParameters("account_id", accountId); VlanMappingDirtyVO vo = findOneBy(sc); if (vo == null) { @@ -33,7 +32,7 @@ public class VlanMappingDirtyDaoImpl extends @Override public void markDirty(long accountId) { - SearchCriteria sc = AllFieldsSearch.create(); + SearchCriteria sc = AccountIdSearch.create(); sc.setParameters("account_id", accountId); VlanMappingDirtyVO vo = findOneBy(sc); if (vo == null) { @@ -47,7 +46,7 @@ public class VlanMappingDirtyDaoImpl extends @Override public void clean(long accountId) { - SearchCriteria sc = AllFieldsSearch.create(); + SearchCriteria sc = AccountIdSearch.create(); sc.setParameters("account_id", accountId); VlanMappingDirtyVO vo = findOneBy(sc); if (vo == null) { diff --git a/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyVO.java b/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyVO.java index 451fadd5364..7a921609dfc 100644 --- a/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyVO.java +++ b/server/src/com/cloud/network/ovs/dao/VlanMappingDirtyVO.java @@ -42,11 +42,14 @@ public class VlanMappingDirtyVO { return dirty; } - public void markDirty() { - dirty = true; + public void setDirty(boolean dirty) { + this.dirty = dirty; } + public void markDirty() { + setDirty(true); + } public void clean() { - dirty = false; + setDirty(false); } } diff --git a/server/src/com/cloud/network/ovs/dao/VlanMappingVO.java b/server/src/com/cloud/network/ovs/dao/VlanMappingVO.java index f19fe57281d..6f1cbf738be 100644 --- a/server/src/com/cloud/network/ovs/dao/VlanMappingVO.java +++ b/server/src/com/cloud/network/ovs/dao/VlanMappingVO.java @@ -25,7 +25,7 @@ public class VlanMappingVO { private long vlan; @Column(name = "ref") - private int ref; + int ref; public VlanMappingVO(long accountId, long hostId, long vlan) { this.hostId = hostId; @@ -58,6 +58,10 @@ public class VlanMappingVO { return ref; } + public void setRef(int ref) { + this.ref = ref; + } + public void ref() { ref++; }