mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
bug 7722: open vswitch - works at VM start time, need fullsync() and flow clean in next
This commit is contained in:
parent
5c01c42ba7
commit
c94b6acadf
@ -3820,34 +3820,22 @@ public abstract class CitrixResourceBase implements ServerResource {
|
|||||||
return Boolean.valueOf(callHostPlugin(conn, "vmops", "can_bridge_firewall", "host_uuid", _host.uuid));
|
return Boolean.valueOf(callHostPlugin(conn, "vmops", "can_bridge_firewall", "host_uuid", _host.uuid));
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: it's better to move more stuff at host plugin side
|
|
||||||
private Answer execute(OvsSetTagAndFlowCommand cmd) {
|
private Answer execute(OvsSetTagAndFlowCommand cmd) {
|
||||||
Connection conn = getConnection();
|
Connection conn = getConnection();
|
||||||
try {
|
try {
|
||||||
Set<VM> vms = VM.getByNameLabel(conn, cmd.getVmName());
|
|
||||||
VM vm = vms.iterator().next();
|
|
||||||
Set<VIF> vifs = vm.getVIFs(conn);
|
|
||||||
String domId = vm.getDomid(conn).toString();
|
|
||||||
String nwName = Networks.BroadcastScheme.VSwitch.toString();
|
String nwName = Networks.BroadcastScheme.VSwitch.toString();
|
||||||
Network nw = getNetworkByName(conn, nwName);
|
Network nw = getNetworkByName(conn, nwName);
|
||||||
assert nw!= null : "Why there is no vswith network ???";
|
assert nw!= null : "Why there is no vswith network ???";
|
||||||
String bridge = nw.getBridge(conn);
|
String bridge = nw.getBridge(conn);
|
||||||
|
|
||||||
/*If VM is domainRouter, this will try to set flow and tag on its
|
/*If VM is domainRouter, this will try to set flow and tag on its
|
||||||
* none guest network nic. don't worry, it will fail sciently at host
|
* none guest network nic. don't worry, it will fail silently at host
|
||||||
* plugin side
|
* plugin side
|
||||||
*/
|
*/
|
||||||
for (VIF vif : vifs) {
|
String result = callHostPlugin(conn, "vmops", "ovs_set_tag_and_flow", "bridge", bridge,
|
||||||
String vifName = "vif" + domId + vif.getDevice(conn);
|
"vmName", cmd.getVmName(), "vlans", cmd.getVlans());
|
||||||
String result = callHostPlugin(conn, "vmops", "vlanRemapUtils", "op", "createFlow", "bridge",
|
s_logger.debug("set flow for " + cmd.getVmName() + " " + result);
|
||||||
bridge, "vifName", vifName, "mac",
|
|
||||||
vif.getMAC(conn), "remap", cmd.getVlans(),
|
|
||||||
"ip", "placeholder now");
|
|
||||||
s_logger.debug("set flow for " + vifName + " on " + cmd.getVmName() + " " + result);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (result.equalsIgnoreCase("SUCCESS")) {
|
if (result.equalsIgnoreCase("SUCCESS")) {
|
||||||
return new Answer(cmd, true, "Set flow for " + cmd.getVmName()
|
return new Answer(cmd, true, "Set flow for " + cmd.getVmName()
|
||||||
+ " success, vlans:" + cmd.getVlans());
|
+ " success, vlans:" + cmd.getVlans());
|
||||||
@ -3855,9 +3843,6 @@ public abstract class CitrixResourceBase implements ServerResource {
|
|||||||
return new Answer(cmd, false, "Set flow for " + cmd.getVmName()
|
return new Answer(cmd, false, "Set flow for " + cmd.getVmName()
|
||||||
+ " failed, vlans:" + cmd.getVlans());
|
+ " failed, vlans:" + cmd.getVlans());
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
return new Answer(cmd, true, "Set flow for " + cmd.getVmName()
|
|
||||||
+ " success, vlans:" + cmd.getVlans());
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -338,7 +338,7 @@ def formatARPFlow(bridge, inPort, vlan, ports):
|
|||||||
actions=strip_vlan,%s" % (inPort, vlan, outputs)
|
actions=strip_vlan,%s" % (inPort, vlan, outputs)
|
||||||
return flow
|
return flow
|
||||||
|
|
||||||
def createFlow (bridge, vifName, mac, ip, vlan, remap):
|
def createFlow (bridge, vifName, mac, remap):
|
||||||
inport = getGreOfPorts(bridge)
|
inport = getGreOfPorts(bridge)
|
||||||
if len(inport) == 0:
|
if len(inport) == 0:
|
||||||
log("WARNING: no inport found")
|
log("WARNING: no inport found")
|
||||||
@ -357,7 +357,7 @@ def createFlow (bridge, vifName, mac, ip, vlan, remap):
|
|||||||
delFlow(mac)
|
delFlow(mac)
|
||||||
|
|
||||||
#set remap here, remap has format e.g. [1,22,200,13,16]
|
#set remap here, remap has format e.g. [1,22,200,13,16]
|
||||||
remap = strip(remap, "both")
|
remap = strip(remap)
|
||||||
log("")
|
log("")
|
||||||
log("Create flow for remap")
|
log("Create flow for remap")
|
||||||
noneGreOfPorts = getNoneGreOfPort(bridge)
|
noneGreOfPorts = getNoneGreOfPort(bridge)
|
||||||
@ -366,7 +366,7 @@ def createFlow (bridge, vifName, mac, ip, vlan, remap):
|
|||||||
log("WARNING: no none GRE ofports found, no ARP flow will be created")
|
log("WARNING: no none GRE ofports found, no ARP flow will be created")
|
||||||
isARP = False
|
isARP = False
|
||||||
|
|
||||||
for j in remap.split(","):
|
for j in remap.split("/"):
|
||||||
delARPFlow(j)
|
delARPFlow(j)
|
||||||
for i in inport:
|
for i in inport:
|
||||||
flow = formatFlow(i, j, mac, output)
|
flow = formatFlow(i, j, mac, output)
|
||||||
@ -383,8 +383,19 @@ def createFlow (bridge, vifName, mac, ip, vlan, remap):
|
|||||||
return 0
|
return 0
|
||||||
######################## End Flow creation utils ##########################
|
######################## End Flow creation utils ##########################
|
||||||
|
|
||||||
def setTag(vifName, vlan):
|
def setTag(bridge, vifName, vlan):
|
||||||
log("")
|
# The startVM command is slow, we may wait for a while for it creates vif on
|
||||||
|
# open vswitch
|
||||||
|
log("Waiting for %s ..." % vifName)
|
||||||
|
waitPortCmd = [vsctlPath, "--timeout=10 wait-until port %s -- get port %s name" % \
|
||||||
|
(vifName, vifName)]
|
||||||
|
doCmd (waitPortCmd)
|
||||||
|
log("%s is here" % vifName)
|
||||||
|
|
||||||
|
if getVifPort(bridge, vifName) == None:
|
||||||
|
log("WARNING: %s is not on bridge %s" % (vifName, bridge))
|
||||||
|
return 0
|
||||||
|
|
||||||
log("Set tag")
|
log("Set tag")
|
||||||
setTagCmd = [vsctlPath, "set port", vifName, "tag=%s"%vlan]
|
setTagCmd = [vsctlPath, "set port", vifName, "tag=%s"%vlan]
|
||||||
doCmd (setTagCmd)
|
doCmd (setTagCmd)
|
||||||
@ -398,20 +409,22 @@ def doCreateGRE(bridge, remoteIP, key):
|
|||||||
log("WARNING: create GRE tunnel on %s for %s success" % (bridge, \
|
log("WARNING: create GRE tunnel on %s for %s success" % (bridge, \
|
||||||
remoteIP))
|
remoteIP))
|
||||||
|
|
||||||
def doCreateFlow (bridge, vifName, mac, ip, vlan, remap):
|
def doCreateFlow (bridge, vifName, mac, remap):
|
||||||
setTag (vifName, vlan)
|
if createFlow(bridge, vifName, mac, remap) < 0:
|
||||||
if createFlow(bridge, vifName, mac, ip, vlan, remap) < 0:
|
log ("Create flow failed(bridge=%s, vifName=%s, mac=%s,\
|
||||||
log ("Create flow failed(bridge=%s, vifName=%s, mac=%s, ip=%s, vlan=%s,\
|
remap=%s" % (bridge, vifName, mac, remap))
|
||||||
remap=%s" % (bridge, vifName, mac, ip, vlan, remap))
|
|
||||||
else:
|
else:
|
||||||
log ("Create flow success(bridge=%s, vifName=%s, mac=%s, ip=%s, vlan=%s,\
|
log ("Create flow success(bridge=%s, vifName=%s, mac=%s,\
|
||||||
remap=%s" % (bridge, vifName, mac, ip, vlan, remap))
|
remap=%s" % (bridge, vifName, mac, remap))
|
||||||
|
|
||||||
|
def doSetTag (bridge, vifName, tag):
|
||||||
|
setTag(bridge, vifName, tag)
|
||||||
|
|
||||||
def doDeleteFlow(bridge, vifName, mac, remap):
|
def doDeleteFlow(bridge, vifName, mac, remap):
|
||||||
delFlow(mac)
|
delFlow(mac)
|
||||||
log("Delete flows for %s" % mac)
|
log("Delete flows for %s" % mac)
|
||||||
|
|
||||||
remap = strip(remap, "both")
|
remap = strip(remap)
|
||||||
|
|
||||||
# remove our port from arp flow
|
# remove our port from arp flow
|
||||||
inport = getGreOfPorts(bridge)
|
inport = getGreOfPorts(bridge)
|
||||||
@ -423,7 +436,7 @@ def doDeleteFlow(bridge, vifName, mac, remap):
|
|||||||
noneGreOfPorts.remove(mine)
|
noneGreOfPorts.remove(mine)
|
||||||
log("Delete ARP flows for(vifname=%s, ofport=%s)" % (vifName, mine))
|
log("Delete ARP flows for(vifname=%s, ofport=%s)" % (vifName, mine))
|
||||||
|
|
||||||
for j in remap.split(","):
|
for j in remap.split("/"):
|
||||||
delARPFlow(j)
|
delARPFlow(j)
|
||||||
for i in inport:
|
for i in inport:
|
||||||
flow = formatARPFlow(bridge, i, j, noneGreOfPorts)
|
flow = formatARPFlow(bridge, i, j, noneGreOfPorts)
|
||||||
@ -457,14 +470,12 @@ if __name__ == "__main__":
|
|||||||
key = sys.argv[4]
|
key = sys.argv[4]
|
||||||
doCreateGRE(bridge, remoteIP, key)
|
doCreateGRE(bridge, remoteIP, key)
|
||||||
elif op == "createFlow":
|
elif op == "createFlow":
|
||||||
checkArgNum(8)
|
checkArgNum(6)
|
||||||
bridge = sys.argv[2]
|
bridge = sys.argv[2]
|
||||||
vifName = sys.argv[3]
|
vifName = sys.argv[3]
|
||||||
mac = sys.argv[4]
|
mac = sys.argv[4]
|
||||||
vlan = sys.argv[5]
|
remap = sys.argv[5]
|
||||||
remap = sys.argv[6]
|
doCreateFlow(bridge, vifName, mac, remap)
|
||||||
ip = sys.argv[7]
|
|
||||||
doCreateFlow(bridge, vifName, mac, ip, vlan, remap)
|
|
||||||
elif op == "deleteFlow":
|
elif op == "deleteFlow":
|
||||||
checkArgNum(6)
|
checkArgNum(6)
|
||||||
bridge = sys.argv[2]
|
bridge = sys.argv[2]
|
||||||
@ -472,6 +483,12 @@ if __name__ == "__main__":
|
|||||||
mac = sys.argv[4]
|
mac = sys.argv[4]
|
||||||
remap = sys.argv[5]
|
remap = sys.argv[5]
|
||||||
doDeleteFlow(bridge, vifName, mac, remap)
|
doDeleteFlow(bridge, vifName, mac, remap)
|
||||||
|
elif op == "setTag":
|
||||||
|
checkArgNum(5)
|
||||||
|
bridge = sys.argv[2]
|
||||||
|
vifName = sys.argv[3]
|
||||||
|
tag = sys.argv[4]
|
||||||
|
doSetTag(bridge, vifName, tag)
|
||||||
else:
|
else:
|
||||||
log("WARNING: get an unkown op %s" % op)
|
log("WARNING: get an unkown op %s" % op)
|
||||||
result=errors["ERROR_OP"]
|
result=errors["ERROR_OP"]
|
||||||
|
|||||||
@ -144,14 +144,16 @@ def vlanRemapUtils(session, args):
|
|||||||
cmd.insert(3, args.pop("bridge"))
|
cmd.insert(3, args.pop("bridge"))
|
||||||
cmd.insert(4, args.pop("vifName"))
|
cmd.insert(4, args.pop("vifName"))
|
||||||
cmd.insert(5, args.pop("mac"))
|
cmd.insert(5, args.pop("mac"))
|
||||||
cmd.insert(6, args.pop("vlan"))
|
|
||||||
cmd.insert(7, args.pop("remap"))
|
cmd.insert(7, args.pop("remap"))
|
||||||
cmd.insert(8, args.pop("ip"))
|
|
||||||
elif op == "deleteFlow":
|
elif op == "deleteFlow":
|
||||||
cmd.insert(3, args.pop("bridge"))
|
cmd.insert(3, args.pop("bridge"))
|
||||||
cmd.insert(4, args.pop("vifName"))
|
cmd.insert(4, args.pop("vifName"))
|
||||||
cmd.insert(5, args.pop("mac"))
|
cmd.insert(5, args.pop("mac"))
|
||||||
cmd.insert(6, args.pop("remap"))
|
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"))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
txt = util.pread2(cmd)
|
txt = util.pread2(cmd)
|
||||||
@ -552,6 +554,47 @@ def default_ebtables_rules(vm_name, vif, vm_ip, vm_mac):
|
|||||||
util.SMlog("Failed to program default ebtables OUT rules")
|
util.SMlog("Failed to program default ebtables OUT rules")
|
||||||
return 'false'
|
return 'false'
|
||||||
|
|
||||||
|
def ovs_set_tag_and_flow(session, args):
|
||||||
|
def get_vif_field(name, field):
|
||||||
|
return session.xenapi.VIF.get_record(name).get(field)
|
||||||
|
|
||||||
|
bridge = args.pop('bridge')
|
||||||
|
vm_name = args.pop('vmName')
|
||||||
|
vlanStr = args.pop('vlans')
|
||||||
|
|
||||||
|
try:
|
||||||
|
vm = session.xenapi.VM.get_by_name_label(vm_name)
|
||||||
|
if len(vm) != 1:
|
||||||
|
return 'false'
|
||||||
|
vm_rec = session.xenapi.VM.get_record(vm[0])
|
||||||
|
vm_vifs = vm_rec.get('VIFs')
|
||||||
|
vifrs = []
|
||||||
|
for vif in vm_vifs:
|
||||||
|
rec = (get_vif_field(vif, 'device'), get_vif_field(vif, 'MAC'))
|
||||||
|
vifrs.append(rec)
|
||||||
|
domid = vm_rec.get('domid')
|
||||||
|
except:
|
||||||
|
util.SMlog("### Failed to get domid or vif list for vm ##" + vm_name)
|
||||||
|
return 'false'
|
||||||
|
|
||||||
|
if domid == '-1':
|
||||||
|
util.SMlog("### Failed to get domid for vm (-1): " + vm_name)
|
||||||
|
return 'false'
|
||||||
|
|
||||||
|
if len(vifrs) == 0:
|
||||||
|
return 'SUCCESS'
|
||||||
|
|
||||||
|
if vlanStr.startswith("/"): vlanStr = vlanStr[1:]
|
||||||
|
if vlanStr.endswith("/"): vlanStr = vlanStr[:-1]
|
||||||
|
vlans = vlanStr.split("/")
|
||||||
|
for vifr in vifrs:
|
||||||
|
vifName = "vif" + domid + "." + vifr[0]
|
||||||
|
mac = vifr[1]
|
||||||
|
vlanRemapUtils(session, {"op":"setTag", "vifName":vifName, "bridge":bridge, "tag":vlans[0]})
|
||||||
|
vlanRemapUtils(session, {"op":"createFlow", "vifName":vifName, "bridge":bridge, "mac":mac, "remap":vlanStr})
|
||||||
|
|
||||||
|
return 'SUCCESS'
|
||||||
|
|
||||||
@echo
|
@echo
|
||||||
def default_network_rules_systemvm(session, args):
|
def default_network_rules_systemvm(session, args):
|
||||||
vm_name = args.pop('vmName')
|
vm_name = args.pop('vmName')
|
||||||
@ -627,9 +670,9 @@ def default_network_rules(session, args):
|
|||||||
vifs = [vif]
|
vifs = [vif]
|
||||||
try:
|
try:
|
||||||
util.pread2(['ifconfig', tap])
|
util.pread2(['ifconfig', tap])
|
||||||
vifs.append(tap)
|
vifs.append(tap)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
delete_rules_for_vm_in_bridge_firewall_chain(vm_name)
|
delete_rules_for_vm_in_bridge_firewall_chain(vm_name)
|
||||||
|
|
||||||
@ -669,7 +712,7 @@ def default_network_rules(session, args):
|
|||||||
return 'false'
|
return 'false'
|
||||||
|
|
||||||
for v in vifs:
|
for v in vifs:
|
||||||
default_ebtables_rules(vm_name, v, vm_ip, vm_mac)
|
default_ebtables_rules(vm_name, v, vm_ip, vm_mac)
|
||||||
|
|
||||||
if write_rule_log_for_vm(vmName, vm_id, vm_ip, domid, '_initial_', '-1') == False:
|
if write_rule_log_for_vm(vmName, vm_id, vm_ip, domid, '_initial_', '-1') == False:
|
||||||
util.SMlog("Failed to log default network rules, ignoring")
|
util.SMlog("Failed to log default network rules, ignoring")
|
||||||
@ -983,9 +1026,9 @@ def network_rules(session, args):
|
|||||||
vifs = [vif]
|
vifs = [vif]
|
||||||
try:
|
try:
|
||||||
util.pread2(['ifconfig', tap])
|
util.pread2(['ifconfig', tap])
|
||||||
vifs.append(tap)
|
vifs.append(tap)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
vm_name = '-'.join(vm_name.split('-')[:-1])
|
vm_name = '-'.join(vm_name.split('-')[:-1])
|
||||||
vmchain = vm_name
|
vmchain = vm_name
|
||||||
|
|
||||||
@ -1064,5 +1107,5 @@ def network_rules(session, args):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
XenAPIPlugin.dispatch({"pingtest": pingtest, "setup_iscsi":setup_iscsi, "gethostvmstats": gethostvmstats, "getvncport": getvncport, "getgateway": getgateway, "preparemigration": preparemigration, "setIptables": setIptables, "pingdomr": pingdomr, "pingxenserver": pingxenserver, "ipassoc": ipassoc, "vm_data": vm_data, "savePassword": savePassword, "saveDhcpEntry": saveDhcpEntry, "setFirewallRule": setFirewallRule, "setLoadBalancerRule": setLoadBalancerRule, "createFile": createFile, "deleteFile": deleteFile, "networkUsage": networkUsage, "network_rules":network_rules, "can_bridge_firewall":can_bridge_firewall, "default_network_rules":default_network_rules, "destroy_network_rules_for_vm":destroy_network_rules_for_vm, "default_network_rules_systemvm":default_network_rules_systemvm, "get_rule_logs_for_vms":get_rule_logs_for_vms, "setLinkLocalIP":setLinkLocalIP, "lt2p_vpn":lt2p_vpn, "vlanRemapUtils":vlanRemapUtils,"cleanup_rules":cleanup_rules})
|
XenAPIPlugin.dispatch({"pingtest": pingtest, "setup_iscsi":setup_iscsi, "gethostvmstats": gethostvmstats, "getvncport": getvncport, "getgateway": getgateway, "preparemigration": preparemigration, "setIptables": setIptables, "pingdomr": pingdomr, "pingxenserver": pingxenserver, "ipassoc": ipassoc, "vm_data": vm_data, "savePassword": savePassword, "saveDhcpEntry": saveDhcpEntry, "setFirewallRule": setFirewallRule, "setLoadBalancerRule": setLoadBalancerRule, "createFile": createFile, "deleteFile": deleteFile, "networkUsage": networkUsage, "network_rules":network_rules, "can_bridge_firewall":can_bridge_firewall, "default_network_rules":default_network_rules, "destroy_network_rules_for_vm":destroy_network_rules_for_vm, "default_network_rules_systemvm":default_network_rules_systemvm, "get_rule_logs_for_vms":get_rule_logs_for_vms, "setLinkLocalIP":setLinkLocalIP, "lt2p_vpn":lt2p_vpn,"cleanup_rules":cleanup_rules,"vlanRemapUtils":vlanRemapUtils, "ovs_set_tag_and_flow":ovs_set_tag_and_flow})
|
||||||
|
|
||||||
|
|||||||
@ -31,3 +31,4 @@ call_firewall.sh=../../../../network/domr/,0755,/opt/xensource/bin
|
|||||||
call_loadbalancer.sh=../../../../network/domr/,0755,/opt/xensource/bin
|
call_loadbalancer.sh=../../../../network/domr/,0755,/opt/xensource/bin
|
||||||
l2tp_vpn.sh=../../../../network/domr/,0755,/opt/xensource/bin
|
l2tp_vpn.sh=../../../../network/domr/,0755,/opt/xensource/bin
|
||||||
cloud-setup-bonding.sh=..,0755,/opt/xensource/bin
|
cloud-setup-bonding.sh=..,0755,/opt/xensource/bin
|
||||||
|
vlanRemapUtils.py=..,0755,/opt/xensource/bin
|
||||||
|
|||||||
@ -73,8 +73,10 @@ import com.cloud.network.dao.RemoteAccessVpnDaoImpl;
|
|||||||
import com.cloud.network.dao.VpnUserDaoImpl;
|
import com.cloud.network.dao.VpnUserDaoImpl;
|
||||||
import com.cloud.network.lb.LoadBalancingRulesManagerImpl;
|
import com.cloud.network.lb.LoadBalancingRulesManagerImpl;
|
||||||
import com.cloud.network.ovs.OvsNetworkManagerImpl;
|
import com.cloud.network.ovs.OvsNetworkManagerImpl;
|
||||||
|
import com.cloud.network.ovs.dao.OvsWorkDaoImpl;
|
||||||
import com.cloud.network.ovs.dao.VlanMappingDaoImpl;
|
import com.cloud.network.ovs.dao.VlanMappingDaoImpl;
|
||||||
import com.cloud.network.ovs.dao.VlanMappingDirtyDaoImpl;
|
import com.cloud.network.ovs.dao.VlanMappingDirtyDaoImpl;
|
||||||
|
import com.cloud.network.ovs.dao.VmFlowLogDaoImpl;
|
||||||
import com.cloud.network.router.VirtualNetworkApplianceManagerImpl;
|
import com.cloud.network.router.VirtualNetworkApplianceManagerImpl;
|
||||||
import com.cloud.network.rules.RulesManagerImpl;
|
import com.cloud.network.rules.RulesManagerImpl;
|
||||||
import com.cloud.network.rules.dao.PortForwardingRulesDaoImpl;
|
import com.cloud.network.rules.dao.PortForwardingRulesDaoImpl;
|
||||||
@ -241,6 +243,8 @@ public class DefaultComponentLibrary implements ComponentLibrary {
|
|||||||
addDao("ClusterDetailsDao", ClusterDetailsDaoImpl.class);
|
addDao("ClusterDetailsDao", ClusterDetailsDaoImpl.class);
|
||||||
addDao("VlanMappingDao", VlanMappingDaoImpl.class);
|
addDao("VlanMappingDao", VlanMappingDaoImpl.class);
|
||||||
addDao("VlanMappingDirtyDao", VlanMappingDirtyDaoImpl.class);
|
addDao("VlanMappingDirtyDao", VlanMappingDirtyDaoImpl.class);
|
||||||
|
addDao("OvsWorkDao", OvsWorkDaoImpl.class);
|
||||||
|
addDao("VmFlowLogDao", VmFlowLogDaoImpl.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, ComponentInfo<Manager>> _managers = new HashMap<String, ComponentInfo<Manager>>();
|
Map<String, ComponentInfo<Manager>> _managers = new HashMap<String, ComponentInfo<Manager>>();
|
||||||
|
|||||||
@ -252,6 +252,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@DB
|
||||||
public PublicIp assignSourceNatIpAddress(Account owner, Network network, long callerId) throws ConcurrentOperationException, InsufficientAddressCapacityException {
|
public PublicIp assignSourceNatIpAddress(Account owner, Network network, long callerId) throws ConcurrentOperationException, InsufficientAddressCapacityException {
|
||||||
assert (network.getTrafficType() != null) : "You're asking for a source nat but your network can't participate in source nat. What do you have to say for yourself?";
|
assert (network.getTrafficType() != null) : "You're asking for a source nat but your network can't participate in source nat. What do you have to say for yourself?";
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@ import com.cloud.exception.ConcurrentOperationException;
|
|||||||
import com.cloud.exception.InsufficientCapacityException;
|
import com.cloud.exception.InsufficientCapacityException;
|
||||||
import com.cloud.exception.ResourceUnavailableException;
|
import com.cloud.exception.ResourceUnavailableException;
|
||||||
import com.cloud.network.Network;
|
import com.cloud.network.Network;
|
||||||
|
import com.cloud.network.Networks;
|
||||||
import com.cloud.network.PublicIpAddress;
|
import com.cloud.network.PublicIpAddress;
|
||||||
import com.cloud.network.Network.Capability;
|
import com.cloud.network.Network.Capability;
|
||||||
import com.cloud.network.Network.Provider;
|
import com.cloud.network.Network.Provider;
|
||||||
@ -55,7 +56,15 @@ public class OvsElement extends AdapterBase implements NetworkElement {
|
|||||||
DeployDestination dest, ReservationContext context)
|
DeployDestination dest, ReservationContext context)
|
||||||
throws ConcurrentOperationException, ResourceUnavailableException,
|
throws ConcurrentOperationException, ResourceUnavailableException,
|
||||||
InsufficientCapacityException {
|
InsufficientCapacityException {
|
||||||
_ovsNetworkMgr.CheckAndUpdateDhcpFlow(network);
|
VirtualMachine instance = vm.getVirtualMachine();
|
||||||
|
|
||||||
|
if (instance.getType() == VirtualMachine.Type.DomainRouter) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (network.getTrafficType() == Networks.TrafficType.Guest) {
|
||||||
|
_ovsNetworkMgr.CheckAndUpdateDhcpFlow(network);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import com.cloud.deploy.DeployDestination;
|
|||||||
import com.cloud.network.Network;
|
import com.cloud.network.Network;
|
||||||
import com.cloud.uservm.UserVm;
|
import com.cloud.uservm.UserVm;
|
||||||
import com.cloud.utils.component.Manager;
|
import com.cloud.utils.component.Manager;
|
||||||
|
import com.cloud.vm.DomainRouterVO;
|
||||||
import com.cloud.vm.State;
|
import com.cloud.vm.State;
|
||||||
import com.cloud.vm.UserVmVO;
|
import com.cloud.vm.UserVmVO;
|
||||||
import com.cloud.vm.VirtualMachineProfile;
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
@ -16,12 +17,21 @@ public interface OvsNetworkManager extends Manager {
|
|||||||
|
|
||||||
public String getVlanMapping(long accountId);
|
public String getVlanMapping(long accountId);
|
||||||
|
|
||||||
public void CheckAndCreateTunnel(Commands cmds,
|
public void UserVmCheckAndCreateTunnel(Commands cmds,
|
||||||
VirtualMachineProfile<UserVmVO> profile, DeployDestination dest);
|
VirtualMachineProfile<UserVmVO> profile, DeployDestination dest);
|
||||||
|
|
||||||
public void applyDefaultFlow(Commands cmds,
|
public void applyDefaultFlowToUserVm(Commands cmds,
|
||||||
VirtualMachineProfile<UserVmVO> profile, DeployDestination dest);
|
VirtualMachineProfile<UserVmVO> profile, DeployDestination dest);
|
||||||
|
|
||||||
|
public void applyDefaultFlowToRouter(Commands cmds,
|
||||||
|
VirtualMachineProfile<DomainRouterVO> profile,
|
||||||
|
DeployDestination dest);
|
||||||
|
|
||||||
public void CheckAndUpdateDhcpFlow(Network nw);
|
public void CheckAndUpdateDhcpFlow(Network nw);
|
||||||
|
|
||||||
public void handleVmStateTransition(UserVm userVm, State vmState);
|
public void handleVmStateTransition(UserVm userVm, State vmState);
|
||||||
|
|
||||||
|
public void RouterCheckAndCreateTunnel(Commands cmds,
|
||||||
|
VirtualMachineProfile<DomainRouterVO> profile,
|
||||||
|
DeployDestination dest);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,15 @@
|
|||||||
package com.cloud.network.ovs;
|
package com.cloud.network.ovs;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.ejb.Local;
|
import javax.ejb.Local;
|
||||||
import javax.naming.ConfigurationException;
|
import javax.naming.ConfigurationException;
|
||||||
|
|
||||||
@ -13,6 +20,7 @@ import com.cloud.agent.manager.Commands;
|
|||||||
import com.cloud.configuration.Config;
|
import com.cloud.configuration.Config;
|
||||||
import com.cloud.configuration.dao.ConfigurationDao;
|
import com.cloud.configuration.dao.ConfigurationDao;
|
||||||
import com.cloud.deploy.DeployDestination;
|
import com.cloud.deploy.DeployDestination;
|
||||||
|
import com.cloud.exception.AgentUnavailableException;
|
||||||
import com.cloud.host.HostVO;
|
import com.cloud.host.HostVO;
|
||||||
import com.cloud.host.dao.HostDao;
|
import com.cloud.host.dao.HostDao;
|
||||||
import com.cloud.network.Network;
|
import com.cloud.network.Network;
|
||||||
@ -20,17 +28,27 @@ import com.cloud.network.NetworkVO;
|
|||||||
import com.cloud.network.Networks.BroadcastDomainType;
|
import com.cloud.network.Networks.BroadcastDomainType;
|
||||||
import com.cloud.network.Networks.TrafficType;
|
import com.cloud.network.Networks.TrafficType;
|
||||||
import com.cloud.network.dao.NetworkDao;
|
import com.cloud.network.dao.NetworkDao;
|
||||||
|
import com.cloud.network.ovs.dao.OvsWorkDao;
|
||||||
|
import com.cloud.network.ovs.dao.OvsWorkVO;
|
||||||
|
import com.cloud.network.ovs.dao.OvsWorkVO.Step;
|
||||||
import com.cloud.network.ovs.dao.VlanMappingDao;
|
import com.cloud.network.ovs.dao.VlanMappingDao;
|
||||||
import com.cloud.network.ovs.dao.VlanMappingDirtyDao;
|
import com.cloud.network.ovs.dao.VlanMappingDirtyDao;
|
||||||
import com.cloud.network.ovs.dao.VlanMappingVO;
|
import com.cloud.network.ovs.dao.VlanMappingVO;
|
||||||
|
import com.cloud.network.ovs.dao.VmFlowLogDao;
|
||||||
|
import com.cloud.network.ovs.dao.VmFlowLogVO;
|
||||||
|
import com.cloud.server.ManagementServer;
|
||||||
import com.cloud.uservm.UserVm;
|
import com.cloud.uservm.UserVm;
|
||||||
import com.cloud.utils.Pair;
|
import com.cloud.utils.Pair;
|
||||||
|
import com.cloud.utils.component.ComponentLocator;
|
||||||
import com.cloud.utils.component.Inject;
|
import com.cloud.utils.component.Inject;
|
||||||
|
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||||
|
import com.cloud.utils.db.DB;
|
||||||
import com.cloud.utils.db.Transaction;
|
import com.cloud.utils.db.Transaction;
|
||||||
import com.cloud.vm.DomainRouterVO;
|
import com.cloud.vm.DomainRouterVO;
|
||||||
import com.cloud.vm.NicVO;
|
import com.cloud.vm.NicVO;
|
||||||
import com.cloud.vm.State;
|
import com.cloud.vm.State;
|
||||||
import com.cloud.vm.UserVmVO;
|
import com.cloud.vm.UserVmVO;
|
||||||
|
import com.cloud.vm.VMInstanceVO;
|
||||||
import com.cloud.vm.VirtualMachine;
|
import com.cloud.vm.VirtualMachine;
|
||||||
import com.cloud.vm.VirtualMachineProfile;
|
import com.cloud.vm.VirtualMachineProfile;
|
||||||
import com.cloud.vm.dao.DomainRouterDao;
|
import com.cloud.vm.dao.DomainRouterDao;
|
||||||
@ -49,61 +67,183 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
|
|||||||
@Inject NetworkDao _networkDao;
|
@Inject NetworkDao _networkDao;
|
||||||
@Inject VlanMappingDirtyDao _vlanMappingDirtyDao;
|
@Inject VlanMappingDirtyDao _vlanMappingDirtyDao;
|
||||||
@Inject DomainRouterDao _routerDao;
|
@Inject DomainRouterDao _routerDao;
|
||||||
|
@Inject OvsWorkDao _workDao;
|
||||||
|
@Inject VmFlowLogDao _flowLogDao;
|
||||||
|
@Inject UserVmDao _userVMDao;
|
||||||
String _name;
|
String _name;
|
||||||
boolean _isEnabled;
|
boolean _isEnabled;
|
||||||
|
ScheduledExecutorService _executorPool;
|
||||||
|
ScheduledExecutorService _cleanupExecutor;
|
||||||
|
|
||||||
|
private long _serverId;
|
||||||
|
private final long _timeBetweenCleanups = 30; //seconds
|
||||||
|
|
||||||
|
public class WorkerThread implements Runnable {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
work();
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkerThread() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CleanupThread implements Runnable {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
cleanupFinishedWork();
|
||||||
|
cleanupUnfinishedWork();
|
||||||
|
}
|
||||||
|
|
||||||
|
CleanupThread() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean configure(String name, Map<String, Object> params)
|
public boolean configure(String name, Map<String, Object> params)
|
||||||
throws ConfigurationException {
|
throws ConfigurationException {
|
||||||
_name = name;
|
_name = name;
|
||||||
_isEnabled = _configDao.getValue(Config.OvsNetwork.key()).equalsIgnoreCase("true") ? true : false;
|
_isEnabled = _configDao.getValue(Config.OvsNetwork.key()).equalsIgnoreCase("true") ? true : false;
|
||||||
|
_serverId = ((ManagementServer)ComponentLocator.getComponent(ManagementServer.Name)).getId();
|
||||||
|
_executorPool = Executors.newScheduledThreadPool(10, new NamedThreadFactory("OVS"));
|
||||||
|
_cleanupExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("OVS-Cleanup"));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean start() {
|
public boolean start() {
|
||||||
// TODO Auto-generated method stub
|
if (_isEnabled) {
|
||||||
|
_cleanupExecutor.scheduleAtFixedRate(new CleanupThread(), _timeBetweenCleanups, _timeBetweenCleanups, TimeUnit.SECONDS);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean stop() {
|
public boolean stop() {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return _name;
|
return _name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isOvsNetworkEnabled() {
|
public boolean isOvsNetworkEnabled() {
|
||||||
// TODO Auto-generated method stub
|
|
||||||
return _isEnabled;
|
return _isEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void cleanupFinishedWork() {
|
||||||
|
Date before = new Date(System.currentTimeMillis() - 24*3600*1000l);
|
||||||
|
int numDeleted = _workDao.deleteFinishedWork(before);
|
||||||
|
if (numDeleted > 0) {
|
||||||
|
s_logger.info("Ovs cleanup deleted " + numDeleted + " finished work items older than " + before.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void cleanupUnfinishedWork() {
|
||||||
|
Date before = new Date(System.currentTimeMillis() - 30*1000l);
|
||||||
|
List<OvsWorkVO> unfinished = _workDao.findUnfinishedWork(before);
|
||||||
|
if (unfinished.size() > 0) {
|
||||||
|
s_logger.info("Ovscleanup found " + unfinished.size() + " unfinished work items older than " + before.toString());
|
||||||
|
Set<Long> affectedVms = new HashSet<Long>();
|
||||||
|
for (OvsWorkVO work: unfinished) {
|
||||||
|
affectedVms.add(work.getInstanceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
s_logger.info("Ovs cleanup re-schedule unfinished work");
|
||||||
|
scheduleFlowUpdateToHosts(affectedVms, false, null);
|
||||||
|
} else {
|
||||||
|
s_logger.debug("Ovs cleanup found no unfinished work items older than " + before.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: think about lock, how new VM start when we change rows
|
||||||
|
@DB
|
||||||
|
public void work() {
|
||||||
|
if (s_logger.isTraceEnabled()) {
|
||||||
|
s_logger.trace("Checking the database");
|
||||||
|
}
|
||||||
|
final OvsWorkVO work = _workDao.take(_serverId);
|
||||||
|
if (work == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Long userVmId = work.getInstanceId();
|
||||||
|
UserVm vm = null;
|
||||||
|
Long seqnum = null;
|
||||||
|
s_logger.info("Ovs working on " + work.toString());
|
||||||
|
final Transaction txn = Transaction.currentTxn();
|
||||||
|
txn.start();
|
||||||
|
try {
|
||||||
|
vm = _userVMDao.acquireInLockTable(work.getInstanceId());
|
||||||
|
if (vm == null) {
|
||||||
|
s_logger.warn("Ovs unable to acquire lock on vm id=" + userVmId);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
String vlans = getVlanMapping(vm.getAccountId());
|
||||||
|
Long agentId = null;
|
||||||
|
VmFlowLogVO log = _flowLogDao.findByVmId(userVmId);
|
||||||
|
if (log == null) {
|
||||||
|
s_logger.warn("Ovs cannot find log record for vm id=" + userVmId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
seqnum = log.getLogsequence();
|
||||||
|
|
||||||
|
if (vm != null && vm.getState() == State.Running) {
|
||||||
|
agentId = vm.getHostId();
|
||||||
|
if (agentId != null ) {
|
||||||
|
//TODO: set flow here
|
||||||
|
OvsSetTagAndFlowCommand cmd = new OvsSetTagAndFlowCommand(vm.getName(),vlans);
|
||||||
|
Commands cmds = new Commands(cmd);
|
||||||
|
try {
|
||||||
|
//_agentMgr.send(agentId, cmds, _answerListener);
|
||||||
|
_agentMgr.send(agentId, cmds, null);
|
||||||
|
//TODO: clean dirty in answerListener
|
||||||
|
} catch (AgentUnavailableException e) {
|
||||||
|
s_logger.debug("Unable to send updates for vm: " + userVmId + "(agentid=" + agentId + ")");
|
||||||
|
_workDao.updateStep(work.getInstanceId(), seqnum, Step.Done);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
if (vm != null) {
|
||||||
|
_userVMDao.releaseFromLockTable(userVmId);
|
||||||
|
_workDao.updateStep(work.getId(), Step.Done);
|
||||||
|
}
|
||||||
|
txn.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: think about lock
|
||||||
@Override
|
@Override
|
||||||
|
@DB
|
||||||
public long askVlanId(long accountId, long hostId) {
|
public long askVlanId(long accountId, long hostId) {
|
||||||
assert _isEnabled : "Who call me ??? while OvsNetwokr is not enabled!!!";
|
assert _isEnabled : "Who call me ??? while OvsNetwokr is not enabled!!!";
|
||||||
final Transaction txn = Transaction.currentTxn();
|
final Transaction txn = Transaction.currentTxn();
|
||||||
txn.start();
|
txn.start();
|
||||||
|
|
||||||
List<VlanMappingVO> mappings = _vlanMappingDao.listByAccountIdAndHostId(accountId, hostId);
|
VlanMappingVO currVlan = _vlanMappingDao.findByAccountIdAndHostId(accountId, hostId);
|
||||||
long vlan = 0;
|
long vlan = 0;
|
||||||
|
|
||||||
if (mappings.size() !=0) {
|
if (currVlan != null) {
|
||||||
assert mappings.size() == 1 : "We should only have one vlan for an account on a host";
|
vlan = currVlan.getVlan();
|
||||||
txn.commit();
|
currVlan.ref();
|
||||||
vlan = mappings.get(0).getVlan();
|
_vlanMappingDao.update(currVlan.getId(), currVlan);
|
||||||
s_logger.debug("Already has an Vlan " + vlan + " on host " + hostId
|
s_logger.debug("Already has an Vlan " + vlan + " on host " + hostId
|
||||||
+ " for account " + accountId + ", use it!");
|
+ " for account " + accountId + ", use it, reference count is " + currVlan.getRef());
|
||||||
|
txn.commit();
|
||||||
return vlan;
|
return vlan;
|
||||||
}
|
}
|
||||||
|
|
||||||
mappings = _vlanMappingDao.listByHostId(hostId);
|
List<VlanMappingVO>mappings = _vlanMappingDao.listByHostId(hostId);
|
||||||
if (mappings.size() > 0) {
|
if (mappings.size() > 0) {
|
||||||
ArrayList<Long> vlans = new ArrayList<Long>();
|
ArrayList<Long> vlans = new ArrayList<Long>();
|
||||||
for (VlanMappingVO vo : mappings) {
|
for (VlanMappingVO vo : mappings) {
|
||||||
@ -129,8 +269,9 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@DB
|
||||||
public String getVlanMapping(long accountId) {
|
public String getVlanMapping(long accountId) {
|
||||||
assert _isEnabled : "Who call me ??? while OvsNetwokr is not enabled!!!";
|
assert _isEnabled : "Who call me ??? while OvsNetwork is not enabled!!!";
|
||||||
final Transaction txn = Transaction.currentTxn();
|
final Transaction txn = Transaction.currentTxn();
|
||||||
txn.start();
|
txn.start();
|
||||||
|
|
||||||
@ -151,22 +292,21 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
|
|||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected void CheckAndCreateTunnel(Commands cmds, VMInstanceVO instance,
|
||||||
public void CheckAndCreateTunnel(Commands cmds, VirtualMachineProfile<UserVmVO> profile,
|
|
||||||
DeployDestination dest) {
|
DeployDestination dest) {
|
||||||
if (!_isEnabled) {
|
if (!_isEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UserVmVO userVm = profile.getVirtualMachine();
|
if (instance.getType() != VirtualMachine.Type.User
|
||||||
if (userVm.getType() != VirtualMachine.Type.User) {
|
&& instance.getType() != VirtualMachine.Type.DomainRouter) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
long hostId = dest.getHost().getId();
|
long hostId = dest.getHost().getId();
|
||||||
long accountId = userVm.getAccountId();
|
long accountId = instance.getAccountId();
|
||||||
List<UserVmVO> vms = _userVmDao.listByAccountIdAndHostId(accountId, hostId);
|
List<UserVmVO> vms = _userVmDao.listByAccountIdAndHostId(accountId, hostId);
|
||||||
if (vms.size() != 0) {
|
if (vms.size() > 1 || (vms.size() == 1 && vms.get(0).getId() != instance.getId())) {
|
||||||
s_logger.debug("Already has GRE tunnel for account " + accountId
|
s_logger.debug("Already has GRE tunnel for account " + accountId
|
||||||
+ " for host " + hostId);
|
+ " for host " + hostId);
|
||||||
return;
|
return;
|
||||||
@ -204,21 +344,19 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
|
|||||||
return sub;
|
return sub;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
protected void applyDefaultFlow(Commands cmds,
|
||||||
public void applyDefaultFlow(Commands cmds,
|
VMInstanceVO instance, DeployDestination dest) {
|
||||||
VirtualMachineProfile<UserVmVO> profile, DeployDestination dest) {
|
|
||||||
if (!_isEnabled) {
|
if (!_isEnabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
UserVmVO userVm = profile.getVirtualMachine();
|
VirtualMachine.Type vmType = instance.getType();
|
||||||
VirtualMachine.Type vmType = userVm.getType();
|
|
||||||
if (vmType != VirtualMachine.Type.User
|
if (vmType != VirtualMachine.Type.User
|
||||||
&& vmType != VirtualMachine.Type.DomainRouter) {
|
&& vmType != VirtualMachine.Type.DomainRouter) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<NicVO> nics = _nicDao.listBy(userVm.getId());
|
List<NicVO> nics = _nicDao.listBy(instance.getId());
|
||||||
if (nics.size() == 0)
|
if (nics.size() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -237,7 +375,7 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
|
|||||||
|
|
||||||
assert nic!=null : "Why there is no guest network nic???";
|
assert nic!=null : "Why there is no guest network nic???";
|
||||||
String vlans = parseVlanAndMapping(nic.getBroadcastUri().toASCIIString());
|
String vlans = parseVlanAndMapping(nic.getBroadcastUri().toASCIIString());
|
||||||
cmds.addCommand(new OvsSetTagAndFlowCommand(userVm.getName(), vlans));
|
cmds.addCommand(new OvsSetTagAndFlowCommand(instance.getName(), vlans));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -267,12 +405,102 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleVmStarted(UserVm userVm) {
|
@DB
|
||||||
|
public void scheduleFlowUpdateToHosts(Set<Long> affectedVms, boolean updateSeqno, Long delayMs) {
|
||||||
|
if (!_isEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (affectedVms == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (delayMs == null)
|
||||||
|
delayMs = new Long(100l);
|
||||||
|
|
||||||
|
for (Long vmId: affectedVms) {
|
||||||
|
Transaction txn = Transaction.currentTxn();
|
||||||
|
txn.start();
|
||||||
|
VmFlowLogVO log = null;
|
||||||
|
OvsWorkVO work = null;
|
||||||
|
UserVm vm = null;
|
||||||
|
try {
|
||||||
|
vm = _userVMDao.acquireInLockTable(vmId);
|
||||||
|
if (vm == null) {
|
||||||
|
s_logger.warn("Ovs failed to acquire lock on vm id " + vmId);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
log = _flowLogDao.findByVmId(vmId);
|
||||||
|
if (log == null) {
|
||||||
|
log = new VmFlowLogVO(vmId);
|
||||||
|
log = _flowLogDao.persist(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log != null && updateSeqno){
|
||||||
|
log.incrLogsequence();
|
||||||
|
_flowLogDao.update(log.getId(), log);
|
||||||
|
}
|
||||||
|
|
||||||
|
work = _workDao.findByVmIdStep(vmId, Step.Scheduled);
|
||||||
|
if (work == null) {
|
||||||
|
work = new OvsWorkVO(vmId, null, null, OvsWorkVO.Step.Scheduled, null);
|
||||||
|
work = _workDao.persist(work);
|
||||||
|
}
|
||||||
|
|
||||||
|
work.setLogsequenceNumber(log.getLogsequence());
|
||||||
|
_workDao.update(work.getId(), work);
|
||||||
|
} finally {
|
||||||
|
if (vm != null) {
|
||||||
|
_userVMDao.releaseFromLockTable(vmId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
txn.commit();
|
||||||
|
|
||||||
|
_executorPool.schedule(new WorkerThread(), delayMs, TimeUnit.MILLISECONDS);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Set<Long> getAffectedVms(UserVm userVm) {
|
||||||
|
long accountId = userVm.getAccountId();
|
||||||
|
if (!_vlanMappingDirtyDao.isDirty(accountId)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<Long> affectedVms = new HashSet<Long>();
|
||||||
|
List<UserVmVO> vms = _userVmDao.listByAccountId(accountId);
|
||||||
|
for (UserVmVO vm : vms) {
|
||||||
|
affectedVms.add(new Long(vm.getId()));
|
||||||
|
}
|
||||||
|
return affectedVms;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleVmStateChange(UserVm userVm) {
|
||||||
|
Set<Long> affectedVms = getAffectedVms(userVm);
|
||||||
scheduleFlowUpdateToHosts(affectedVms, true, null);
|
scheduleFlowUpdateToHosts(affectedVms, true, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleVmStopped(UserVm userVm) {
|
//TODO: think about lock
|
||||||
scheduleFlowUpdateToHosts(affectedVms, true, null);
|
protected void checkAndRemove(UserVm userVm) {
|
||||||
|
long accountId = userVm.getAccountId();
|
||||||
|
long hostId = userVm.getHostId();
|
||||||
|
|
||||||
|
final Transaction txn = Transaction.currentTxn();
|
||||||
|
txn.start();
|
||||||
|
VlanMappingVO vo = _vlanMappingDao.findByAccountIdAndHostId(accountId, hostId);
|
||||||
|
if (vo.unref() == 0) {
|
||||||
|
_vlanMappingDao.remove(vo.getId());
|
||||||
|
s_logger.debug(userVm.getName() + " is the last one on host "
|
||||||
|
+ hostId + " for account " + accountId
|
||||||
|
+ ", remove vlan in ovs_host_vlan_alloc");
|
||||||
|
_vlanMappingDirtyDao.markDirty(accountId);
|
||||||
|
} else {
|
||||||
|
_vlanMappingDao.update(vo.getId(), vo);
|
||||||
|
s_logger.debug(userVm.getName()
|
||||||
|
+ " reduces reference count of (account,host) = ("
|
||||||
|
+ accountId + "," + hostId + ") to " + vo.getRef());
|
||||||
|
}
|
||||||
|
txn.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -291,14 +519,42 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
|
|||||||
case Unknown:
|
case Unknown:
|
||||||
return;
|
return;
|
||||||
case Running:
|
case Running:
|
||||||
handleVmStarted(userVm);
|
handleVmStateChange(userVm);
|
||||||
break;
|
break;
|
||||||
case Stopping:
|
case Stopping:
|
||||||
case Stopped:
|
case Stopped:
|
||||||
handleVmStopped(userVm);
|
checkAndRemove(userVm);
|
||||||
|
handleVmStateChange(userVm);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void UserVmCheckAndCreateTunnel(Commands cmds,
|
||||||
|
VirtualMachineProfile<UserVmVO> profile, DeployDestination dest) {
|
||||||
|
CheckAndCreateTunnel(cmds, (VMInstanceVO)profile.getVirtualMachine(), dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void RouterCheckAndCreateTunnel(Commands cmds,
|
||||||
|
VirtualMachineProfile<DomainRouterVO> profile,
|
||||||
|
DeployDestination dest) {
|
||||||
|
CheckAndCreateTunnel(cmds, (VMInstanceVO)profile.getVirtualMachine(), dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyDefaultFlowToUserVm(Commands cmds,
|
||||||
|
VirtualMachineProfile<UserVmVO> profile, DeployDestination dest) {
|
||||||
|
applyDefaultFlow(cmds, profile.getVirtualMachine(), dest);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyDefaultFlowToRouter(Commands cmds,
|
||||||
|
VirtualMachineProfile<DomainRouterVO> profile,
|
||||||
|
DeployDestination dest) {
|
||||||
|
applyDefaultFlow(cmds, profile.getVirtualMachine(), dest);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
23
server/src/com/cloud/network/ovs/dao/OvsWorkDao.java
Normal file
23
server/src/com/cloud/network/ovs/dao/OvsWorkDao.java
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
package com.cloud.network.ovs.dao;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.cloud.network.ovs.dao.OvsWorkVO.Step;
|
||||||
|
import com.cloud.utils.db.GenericDao;
|
||||||
|
|
||||||
|
public interface OvsWorkDao extends GenericDao<OvsWorkVO, Long> {
|
||||||
|
OvsWorkVO findByVmId(long vmId, boolean taken);
|
||||||
|
|
||||||
|
OvsWorkVO findByVmIdStep(long vmId, Step step);
|
||||||
|
|
||||||
|
OvsWorkVO take(long serverId);
|
||||||
|
|
||||||
|
void updateStep(Long vmId, Long logSequenceNumber, Step done);
|
||||||
|
|
||||||
|
void updateStep(Long workId, Step done);
|
||||||
|
|
||||||
|
int deleteFinishedWork(Date timeBefore);
|
||||||
|
|
||||||
|
List<OvsWorkVO> findUnfinishedWork(Date timeBefore);
|
||||||
|
}
|
||||||
187
server/src/com/cloud/network/ovs/dao/OvsWorkDaoImpl.java
Normal file
187
server/src/com/cloud/network/ovs/dao/OvsWorkDaoImpl.java
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
package com.cloud.network.ovs.dao;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.ejb.Local;
|
||||||
|
import com.cloud.ha.HaWorkVO;
|
||||||
|
import com.cloud.network.ovs.dao.OvsWorkVO.Step;
|
||||||
|
import com.cloud.utils.db.Filter;
|
||||||
|
import com.cloud.utils.db.GenericDaoBase;
|
||||||
|
import com.cloud.utils.db.SearchBuilder;
|
||||||
|
import com.cloud.utils.db.SearchCriteria;
|
||||||
|
import com.cloud.utils.db.SearchCriteria.Op;
|
||||||
|
import com.cloud.utils.db.Transaction;
|
||||||
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
|
|
||||||
|
@Local(value={OvsWorkDao.class})
|
||||||
|
public class OvsWorkDaoImpl extends GenericDaoBase<OvsWorkVO, Long> implements
|
||||||
|
OvsWorkDao {
|
||||||
|
private SearchBuilder<OvsWorkVO> VmIdTakenSearch;
|
||||||
|
private SearchBuilder<OvsWorkVO> VmIdSeqNumSearch;
|
||||||
|
private SearchBuilder<OvsWorkVO> VmIdUnTakenSearch;
|
||||||
|
private SearchBuilder<OvsWorkVO> UntakenWorkSearch;
|
||||||
|
private SearchBuilder<OvsWorkVO> VmIdStepSearch;
|
||||||
|
private SearchBuilder<OvsWorkVO> CleanupSearch;
|
||||||
|
|
||||||
|
|
||||||
|
protected OvsWorkDaoImpl() {
|
||||||
|
VmIdTakenSearch = createSearchBuilder();
|
||||||
|
VmIdTakenSearch.and("vmId", VmIdTakenSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||||
|
VmIdTakenSearch.and("taken", VmIdTakenSearch.entity().getDateTaken(), SearchCriteria.Op.NNULL);
|
||||||
|
|
||||||
|
VmIdTakenSearch.done();
|
||||||
|
|
||||||
|
VmIdUnTakenSearch = createSearchBuilder();
|
||||||
|
VmIdUnTakenSearch.and("vmId", VmIdUnTakenSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||||
|
VmIdUnTakenSearch.and("taken", VmIdUnTakenSearch.entity().getDateTaken(), SearchCriteria.Op.NULL);
|
||||||
|
|
||||||
|
VmIdUnTakenSearch.done();
|
||||||
|
|
||||||
|
UntakenWorkSearch = createSearchBuilder();
|
||||||
|
UntakenWorkSearch.and("server", UntakenWorkSearch.entity().getServerId(), SearchCriteria.Op.NULL);
|
||||||
|
UntakenWorkSearch.and("taken", UntakenWorkSearch.entity().getDateTaken(), SearchCriteria.Op.NULL);
|
||||||
|
UntakenWorkSearch.and("step", UntakenWorkSearch.entity().getStep(), SearchCriteria.Op.EQ);
|
||||||
|
|
||||||
|
UntakenWorkSearch.done();
|
||||||
|
|
||||||
|
VmIdSeqNumSearch = createSearchBuilder();
|
||||||
|
VmIdSeqNumSearch.and("vmId", VmIdSeqNumSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||||
|
VmIdSeqNumSearch.and("seqno", VmIdSeqNumSearch.entity().getLogsequenceNumber(), SearchCriteria.Op.EQ);
|
||||||
|
|
||||||
|
VmIdSeqNumSearch.done();
|
||||||
|
|
||||||
|
VmIdStepSearch = createSearchBuilder();
|
||||||
|
VmIdStepSearch.and("vmId", VmIdStepSearch.entity().getInstanceId(), SearchCriteria.Op.EQ);
|
||||||
|
VmIdStepSearch.and("step", VmIdStepSearch.entity().getStep(), SearchCriteria.Op.EQ);
|
||||||
|
|
||||||
|
VmIdStepSearch.done();
|
||||||
|
|
||||||
|
CleanupSearch = createSearchBuilder();
|
||||||
|
CleanupSearch.and("taken", CleanupSearch.entity().getDateTaken(), Op.LTEQ);
|
||||||
|
CleanupSearch.and("step", CleanupSearch.entity().getStep(), SearchCriteria.Op.IN);
|
||||||
|
|
||||||
|
CleanupSearch.done();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OvsWorkVO findByVmId(long vmId, boolean taken) {
|
||||||
|
SearchCriteria<OvsWorkVO> sc = taken?VmIdTakenSearch.create():VmIdUnTakenSearch.create();
|
||||||
|
sc.setParameters("vmId", vmId);
|
||||||
|
return findOneIncludingRemovedBy(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OvsWorkVO take(long serverId) {
|
||||||
|
final Transaction txn = Transaction.currentTxn();
|
||||||
|
try {
|
||||||
|
final SearchCriteria<OvsWorkVO> sc = UntakenWorkSearch.create();
|
||||||
|
sc.setParameters("step", Step.Scheduled);
|
||||||
|
|
||||||
|
final Filter filter = new Filter(OvsWorkVO.class, null, true, 0l, 1l);//FIXME: order desc by update time?
|
||||||
|
|
||||||
|
txn.start();
|
||||||
|
final List<OvsWorkVO> vos = lockRows(sc, filter, true);
|
||||||
|
if (vos.size() == 0) {
|
||||||
|
txn.commit();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
OvsWorkVO work = null;
|
||||||
|
for (OvsWorkVO w: vos) {
|
||||||
|
//ensure that there is no job in Processing state for the same VM
|
||||||
|
if ( findByVmIdStep(w.getInstanceId(), Step.Processing) == null) {
|
||||||
|
work = w;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (work == null) {
|
||||||
|
txn.commit();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
work.setServerId(serverId);
|
||||||
|
work.setDateTaken(new Date());
|
||||||
|
work.setStep(OvsWorkVO.Step.Processing);
|
||||||
|
|
||||||
|
update(work.getId(), work);
|
||||||
|
|
||||||
|
txn.commit();
|
||||||
|
|
||||||
|
return work;
|
||||||
|
|
||||||
|
} catch (final Throwable e) {
|
||||||
|
throw new CloudRuntimeException("Unable to execute take", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateStep(Long vmId, Long logSequenceNumber, Step step) {
|
||||||
|
final Transaction txn = Transaction.currentTxn();
|
||||||
|
txn.start();
|
||||||
|
SearchCriteria<OvsWorkVO> sc = VmIdSeqNumSearch.create();
|
||||||
|
sc.setParameters("vmId", vmId);
|
||||||
|
sc.setParameters("seqno", logSequenceNumber);
|
||||||
|
|
||||||
|
final Filter filter = new Filter(HaWorkVO.class, null, true, 0l, 1l);
|
||||||
|
|
||||||
|
final List<OvsWorkVO> vos = lockRows(sc, filter, true);
|
||||||
|
if (vos.size() == 0) {
|
||||||
|
txn.commit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
OvsWorkVO work = vos.get(0);
|
||||||
|
work.setStep(step);
|
||||||
|
update(work.getId(), work);
|
||||||
|
|
||||||
|
txn.commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OvsWorkVO findByVmIdStep(long vmId, Step step) {
|
||||||
|
SearchCriteria<OvsWorkVO> sc = VmIdStepSearch.create();
|
||||||
|
sc.setParameters("vmId", vmId);
|
||||||
|
sc.setParameters("step", step);
|
||||||
|
return findOneIncludingRemovedBy(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateStep(Long workId, Step step) {
|
||||||
|
final Transaction txn = Transaction.currentTxn();
|
||||||
|
txn.start();
|
||||||
|
|
||||||
|
OvsWorkVO work = lockRow(workId, true);
|
||||||
|
if (work == null) {
|
||||||
|
txn.commit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
work.setStep(step);
|
||||||
|
update(work.getId(), work);
|
||||||
|
|
||||||
|
txn.commit();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int deleteFinishedWork(Date timeBefore) {
|
||||||
|
final SearchCriteria<OvsWorkVO> sc = CleanupSearch.create();
|
||||||
|
sc.setParameters("taken", timeBefore);
|
||||||
|
sc.setParameters("step", Step.Done);
|
||||||
|
|
||||||
|
return expunge(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<OvsWorkVO> findUnfinishedWork(Date timeBefore) {
|
||||||
|
final SearchCriteria<OvsWorkVO> sc = CleanupSearch.create();
|
||||||
|
sc.setParameters("taken", timeBefore);
|
||||||
|
sc.setParameters("step", Step.Processing);
|
||||||
|
|
||||||
|
List<OvsWorkVO> result = listIncludingRemovedBy(sc);
|
||||||
|
|
||||||
|
OvsWorkVO work = createForUpdate();
|
||||||
|
work.setStep(Step.Error);
|
||||||
|
update(work, sc);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
123
server/src/com/cloud/network/ovs/dao/OvsWorkVO.java
Normal file
123
server/src/com/cloud/network/ovs/dao/OvsWorkVO.java
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
package com.cloud.network.ovs.dao;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.persistence.Temporal;
|
||||||
|
import javax.persistence.TemporalType;
|
||||||
|
|
||||||
|
import com.cloud.utils.db.GenericDao;
|
||||||
|
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="ovs_work")
|
||||||
|
public class OvsWorkVO {
|
||||||
|
public enum Step {
|
||||||
|
Scheduled,
|
||||||
|
Processing,
|
||||||
|
Done,
|
||||||
|
Error
|
||||||
|
}
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy=GenerationType.IDENTITY)
|
||||||
|
@Column(name="id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name="instance_id", updatable=false, nullable=false)
|
||||||
|
private Long instanceId; // vm_instance id
|
||||||
|
|
||||||
|
|
||||||
|
@Column(name="mgmt_server_id", nullable=true)
|
||||||
|
private Long serverId;
|
||||||
|
|
||||||
|
@Column(name=GenericDao.CREATED_COLUMN)
|
||||||
|
private Date created;
|
||||||
|
|
||||||
|
|
||||||
|
@Column(name="step", nullable = false)
|
||||||
|
@Enumerated(value=EnumType.STRING)
|
||||||
|
private Step step;
|
||||||
|
|
||||||
|
@Column(name="taken", nullable=true)
|
||||||
|
@Temporal(value=TemporalType.TIMESTAMP)
|
||||||
|
private Date dateTaken;
|
||||||
|
|
||||||
|
@Column(name="seq_no", nullable=true)
|
||||||
|
private Long logsequenceNumber = null;
|
||||||
|
|
||||||
|
|
||||||
|
protected OvsWorkVO() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getInstanceId() {
|
||||||
|
return instanceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Long getServerId() {
|
||||||
|
return serverId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setServerId(final Long serverId) {
|
||||||
|
this.serverId = serverId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreated() {
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public OvsWorkVO(Long instanceId, Long serverId, Date created,
|
||||||
|
Step step, Date dateTaken) {
|
||||||
|
super();
|
||||||
|
this.instanceId = instanceId;
|
||||||
|
this.serverId = serverId;
|
||||||
|
this.created = created;
|
||||||
|
this.step = step;
|
||||||
|
this.dateTaken = dateTaken;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return new StringBuilder("[Ovs-Work:id=").append(id).append(":vm=").append(instanceId).append("]").toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getDateTaken() {
|
||||||
|
return dateTaken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStep(Step step) {
|
||||||
|
this.step = step;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Step getStep() {
|
||||||
|
return step;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDateTaken(Date date) {
|
||||||
|
dateTaken = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getLogsequenceNumber() {
|
||||||
|
return logsequenceNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLogsequenceNumber(Long logsequenceNumber) {
|
||||||
|
this.logsequenceNumber = logsequenceNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -8,4 +8,5 @@ public interface VlanMappingDao extends GenericDao<VlanMappingVO, Long> {
|
|||||||
List<VlanMappingVO> listByAccountIdAndHostId(long accountId, long hostId);
|
List<VlanMappingVO> listByAccountIdAndHostId(long accountId, long hostId);
|
||||||
List<VlanMappingVO> listByHostId(long hostId);
|
List<VlanMappingVO> listByHostId(long hostId);
|
||||||
List<VlanMappingVO> listByAccountId(long accountId);
|
List<VlanMappingVO> listByAccountId(long accountId);
|
||||||
|
VlanMappingVO findByAccountIdAndHostId(long accountId, long hostId);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,4 +47,11 @@ public class VlanMappingDaoImpl extends GenericDaoBase<VlanMappingVO, Long>
|
|||||||
|
|
||||||
return listBy(sc, null);
|
return listBy(sc, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VlanMappingVO findByAccountIdAndHostId(long accountId, long hostId) {
|
||||||
|
SearchCriteria<VlanMappingVO> sc = AllFieldsSearch.create();
|
||||||
|
sc.setParameters("account_id", accountId);
|
||||||
|
return findOneBy(sc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,11 +23,15 @@ public class VlanMappingVO {
|
|||||||
|
|
||||||
@Column(name = "vlan")
|
@Column(name = "vlan")
|
||||||
private long vlan;
|
private long vlan;
|
||||||
|
|
||||||
|
@Column(name = "ref")
|
||||||
|
private int ref;
|
||||||
|
|
||||||
public VlanMappingVO(long accountId, long hostId, long vlan) {
|
public VlanMappingVO(long accountId, long hostId, long vlan) {
|
||||||
this.hostId = hostId;
|
this.hostId = hostId;
|
||||||
this.accountId = accountId;
|
this.accountId = accountId;
|
||||||
this.vlan = vlan;
|
this.vlan = vlan;
|
||||||
|
this.ref = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public VlanMappingVO() {
|
public VlanMappingVO() {
|
||||||
@ -49,4 +53,17 @@ public class VlanMappingVO {
|
|||||||
public long getId() {
|
public long getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getRef() {
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ref() {
|
||||||
|
ref++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int unref() {
|
||||||
|
ref--;
|
||||||
|
return ref;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
7
server/src/com/cloud/network/ovs/dao/VmFlowLogDao.java
Normal file
7
server/src/com/cloud/network/ovs/dao/VmFlowLogDao.java
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
package com.cloud.network.ovs.dao;
|
||||||
|
|
||||||
|
import com.cloud.utils.db.GenericDao;
|
||||||
|
|
||||||
|
public interface VmFlowLogDao extends GenericDao<VmFlowLogVO, Long> {
|
||||||
|
VmFlowLogVO findByVmId(long vmId);
|
||||||
|
}
|
||||||
27
server/src/com/cloud/network/ovs/dao/VmFlowLogDaoImpl.java
Normal file
27
server/src/com/cloud/network/ovs/dao/VmFlowLogDaoImpl.java
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package com.cloud.network.ovs.dao;
|
||||||
|
|
||||||
|
import com.cloud.utils.db.GenericDaoBase;
|
||||||
|
import com.cloud.utils.db.SearchBuilder;
|
||||||
|
import com.cloud.utils.db.SearchCriteria;
|
||||||
|
import javax.ejb.Local;
|
||||||
|
|
||||||
|
@Local(value={VmFlowLogDao.class})
|
||||||
|
public class VmFlowLogDaoImpl extends GenericDaoBase<VmFlowLogVO, Long>
|
||||||
|
implements VmFlowLogDao {
|
||||||
|
private SearchBuilder<VmFlowLogVO> VmIdSearch;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VmFlowLogVO findByVmId(long vmId) {
|
||||||
|
SearchCriteria<VmFlowLogVO> sc = VmIdSearch.create();
|
||||||
|
sc.setParameters("vmId", vmId);
|
||||||
|
return findOneIncludingRemovedBy(sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected VmFlowLogDaoImpl() {
|
||||||
|
VmIdSearch = createSearchBuilder();
|
||||||
|
VmIdSearch.and("vmId", VmIdSearch.entity().getInstanceId(),
|
||||||
|
SearchCriteria.Op.EQ);
|
||||||
|
VmIdSearch.done();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
59
server/src/com/cloud/network/ovs/dao/VmFlowLogVO.java
Normal file
59
server/src/com/cloud/network/ovs/dao/VmFlowLogVO.java
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package com.cloud.network.ovs.dao;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.GenerationType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
|
||||||
|
import com.cloud.utils.db.GenericDao;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name="ovs_vm_flow_log")
|
||||||
|
public class VmFlowLogVO {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue(strategy=GenerationType.IDENTITY)
|
||||||
|
@Column(name="id")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Column(name="instance_id", updatable=false, nullable=false)
|
||||||
|
private Long instanceId; // vm_instance id
|
||||||
|
|
||||||
|
@Column(name=GenericDao.CREATED_COLUMN)
|
||||||
|
private Date created;
|
||||||
|
|
||||||
|
@Column(name="logsequence")
|
||||||
|
long logsequence;
|
||||||
|
|
||||||
|
protected VmFlowLogVO() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public VmFlowLogVO(Long instanceId) {
|
||||||
|
super();
|
||||||
|
this.instanceId = instanceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getInstanceId() {
|
||||||
|
return instanceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreated() {
|
||||||
|
return created;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLogsequence() {
|
||||||
|
return logsequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void incrLogsequence() {
|
||||||
|
logsequence++;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -129,6 +129,7 @@ import com.cloud.network.dao.VpnUserDao;
|
|||||||
import com.cloud.network.lb.LoadBalancingRule;
|
import com.cloud.network.lb.LoadBalancingRule;
|
||||||
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
|
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
|
||||||
import com.cloud.network.lb.LoadBalancingRulesManager;
|
import com.cloud.network.lb.LoadBalancingRulesManager;
|
||||||
|
import com.cloud.network.ovs.OvsNetworkManager;
|
||||||
import com.cloud.network.router.VirtualRouter.Role;
|
import com.cloud.network.router.VirtualRouter.Role;
|
||||||
import com.cloud.network.rules.FirewallRule;
|
import com.cloud.network.rules.FirewallRule;
|
||||||
import com.cloud.network.rules.PortForwardingRule;
|
import com.cloud.network.rules.PortForwardingRule;
|
||||||
@ -294,6 +295,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
|
|||||||
RemoteAccessVpnDao _vpnDao;
|
RemoteAccessVpnDao _vpnDao;
|
||||||
@Inject
|
@Inject
|
||||||
VMInstanceDao _instanceDao;
|
VMInstanceDao _instanceDao;
|
||||||
|
OvsNetworkManager _ovsNetworkMgr;
|
||||||
|
|
||||||
long _routerTemplateId = -1;
|
long _routerTemplateId = -1;
|
||||||
int _routerRamSize;
|
int _routerRamSize;
|
||||||
@ -1250,6 +1252,9 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
|
|||||||
@Override
|
@Override
|
||||||
public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile<DomainRouterVO> profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException{
|
public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile<DomainRouterVO> profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException{
|
||||||
NicProfile controlNic = (NicProfile) profile.getParameter("control.nic");
|
NicProfile controlNic = (NicProfile) profile.getParameter("control.nic");
|
||||||
|
_ovsNetworkMgr.RouterCheckAndCreateTunnel(cmds, profile, dest);
|
||||||
|
_ovsNetworkMgr.applyDefaultFlowToRouter(cmds, profile, dest);
|
||||||
|
|
||||||
cmds.addCommand("checkSsh", new CheckSshCommand(profile.getInstanceName(), controlNic.getIp4Address(), 3922, 5, 20));
|
cmds.addCommand("checkSsh", new CheckSshCommand(profile.getInstanceName(), controlNic.getIp4Address(), 3922, 5, 20));
|
||||||
|
|
||||||
DomainRouterVO router = profile.getVirtualMachine();
|
DomainRouterVO router = profile.getVirtualMachine();
|
||||||
|
|||||||
@ -1133,7 +1133,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
|
|||||||
public void completeStartCommand(UserVmVO vm) {
|
public void completeStartCommand(UserVmVO vm) {
|
||||||
_itMgr.stateTransitTo(vm, VirtualMachine.Event.AgentReportRunning, vm.getHostId());
|
_itMgr.stateTransitTo(vm, VirtualMachine.Event.AgentReportRunning, vm.getHostId());
|
||||||
_networkGroupMgr.handleVmStateTransition(vm, State.Running);
|
_networkGroupMgr.handleVmStateTransition(vm, State.Running);
|
||||||
|
_ovsNetworkMgr.handleVmStateTransition(vm, State.Running);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1167,6 +1167,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
|
|||||||
|
|
||||||
txn.commit();
|
txn.commit();
|
||||||
_networkGroupMgr.handleVmStateTransition(vm, State.Stopped);
|
_networkGroupMgr.handleVmStateTransition(vm, State.Stopped);
|
||||||
|
_ovsNetworkMgr.handleVmStateTransition(vm, State.Stopped);
|
||||||
} catch (Throwable th) {
|
} catch (Throwable th) {
|
||||||
s_logger.error("Error during stop: ", th);
|
s_logger.error("Error during stop: ", th);
|
||||||
throw new CloudRuntimeException("Error during stop: ", th);
|
throw new CloudRuntimeException("Error during stop: ", th);
|
||||||
@ -2343,7 +2344,10 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
vm = _itMgr.start(vm, null, caller, owner, cmd.getHypervisor());
|
vm = _itMgr.start(vm, null, caller, owner, cmd.getHypervisor());
|
||||||
} finally {
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
updateVmStateForFailedVmCreation(vm.getId());
|
updateVmStateForFailedVmCreation(vm.getId());
|
||||||
}
|
}
|
||||||
vm.setPassword(password);
|
vm.setPassword(password);
|
||||||
@ -2397,7 +2401,8 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
|
|||||||
}
|
}
|
||||||
_vmDao.update(userVm.getId(), userVm);
|
_vmDao.update(userVm.getId(), userVm);
|
||||||
|
|
||||||
_ovsNetworkMgr.CheckAndCreateTunnel(cmds, profile, dest);
|
_ovsNetworkMgr.UserVmCheckAndCreateTunnel(cmds, profile, dest);
|
||||||
|
_ovsNetworkMgr.applyDefaultFlowToUserVm(cmds, profile, dest);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1328,6 +1328,7 @@ CREATE TABLE `cloud`.`ovs_host_vlan_alloc`(
|
|||||||
`host_id` bigint unsigned COMMENT 'host id',
|
`host_id` bigint unsigned COMMENT 'host id',
|
||||||
`account_id` bigint unsigned COMMENT 'account id',
|
`account_id` bigint unsigned COMMENT 'account id',
|
||||||
`vlan` bigint unsigned COMMENT 'vlan id under account #account_id on host #host_id',
|
`vlan` bigint unsigned COMMENT 'vlan id under account #account_id on host #host_id',
|
||||||
|
`ref` int unsigned NOT NULL DEFAULT 0 COMMENT 'reference count',
|
||||||
PRIMARY KEY(`id`)
|
PRIMARY KEY(`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
@ -1338,4 +1339,23 @@ CREATE TABLE `cloud`.`ovs_vlan_mapping_dirty`(
|
|||||||
PRIMARY KEY(`id`)
|
PRIMARY KEY(`id`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
CREATE TABLE `cloud`.`ovs_vm_flow_log` (
|
||||||
|
`id` bigint unsigned UNIQUE NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||||
|
`instance_id` bigint unsigned NOT NULL COMMENT 'vm instance that needs flows to be synced.',
|
||||||
|
`created` datetime NOT NULL COMMENT 'time the entry was requested',
|
||||||
|
`logsequence` bigint unsigned COMMENT 'seq number to be sent to agent, uniquely identifies flow update',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
|
CREATE TABLE `cloud`.`ovs_work` (
|
||||||
|
`id` bigint unsigned UNIQUE NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||||
|
`instance_id` bigint unsigned NOT NULL COMMENT 'vm instance that needs rules to be synced.',
|
||||||
|
`mgmt_server_id` bigint unsigned COMMENT 'management server that has taken up the work of doing rule sync',
|
||||||
|
`created` datetime NOT NULL COMMENT 'time the entry was requested',
|
||||||
|
`taken` datetime COMMENT 'time it was taken by the management server',
|
||||||
|
`step` varchar(32) NOT NULL COMMENT 'Step in the work',
|
||||||
|
`seq_no` bigint unsigned COMMENT 'seq number to be sent to agent, uniquely identifies ruleset update',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||||
|
|
||||||
SET foreign_key_checks = 1;
|
SET foreign_key_checks = 1;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user