fix bug 7722, code complete basic architecture

This commit is contained in:
Frank 2011-01-05 00:57:07 -08:00
parent d84acb204e
commit 5c01c42ba7
21 changed files with 1443 additions and 3 deletions

View File

@ -0,0 +1,26 @@
package com.cloud.network.ovs;
import com.cloud.agent.api.Command;
public class OvsCreateGreTunnelCommand extends Command {
String remoteIp;
String key;
@Override
public boolean executeInSequence() {
return true;
}
public OvsCreateGreTunnelCommand(String remoteIp, String key) {
this.remoteIp = remoteIp;
this.key = key;
}
public String getRemoteIp() {
return remoteIp;
}
public String getKey() {
return key;
}
}

View File

@ -0,0 +1,26 @@
package com.cloud.network.ovs;
import com.cloud.agent.api.Command;
public class OvsSetTagAndFlowCommand extends Command {
String vlans;
String vmName;
@Override
public boolean executeInSequence() {
return true;
}
public String getVlans() {
return vlans;
}
public String getVmName() {
return vmName;
}
public OvsSetTagAndFlowCommand(String vmName, String vlans) {
this.vmName = vmName;
this.vlans = vlans;
}
}

View File

@ -155,9 +155,12 @@ import com.cloud.host.Host.Type;
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.HAProxyConfigurator;
import com.cloud.network.LoadBalancerConfigurator;
import com.cloud.network.Networks;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.IsolationType;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.ovs.OvsCreateGreTunnelCommand;
import com.cloud.network.ovs.OvsSetTagAndFlowCommand;
import com.cloud.resource.ServerResource;
import com.cloud.storage.Storage;
import com.cloud.storage.Storage.ImageFormat;
@ -442,6 +445,10 @@ public abstract class CitrixResourceBase implements ServerResource {
return execute((CheckSshCommand)cmd);
} else if (cmd instanceof SecurityIngressRulesCmd) {
return execute((SecurityIngressRulesCmd) cmd);
} else if (cmd instanceof OvsCreateGreTunnelCommand) {
return execute((OvsCreateGreTunnelCommand)cmd);
} else if (cmd instanceof OvsSetTagAndFlowCommand) {
return execute((OvsSetTagAndFlowCommand)cmd);
} else {
return Answer.createUnsupportedCommandAnswer(cmd);
}
@ -466,6 +473,92 @@ public abstract class CitrixResourceBase implements ServerResource {
throw new CloudRuntimeException("Unsupported network type: " + type);
}
/**
* This is a tricky to create network in xenserver.
* if you create a network then create bridge by brctl or openvswitch yourself,
* then you will get an expection that is "REQUIRED_NETWROK" when you start a
* vm with this network. The soultion is, create a vif of dom0 and plug it in
* network, xenserver will create the bridge on behalf of you
* @throws XmlRpcException
* @throws XenAPIException
*/
private void enableXenServerNetwork(Connection conn, Network nw,
String vifNameLabel, String networkDesc) throws XenAPIException, XmlRpcException {
/* Make sure there is a physical bridge on this network */
VIF dom0vif = null;
Pair<VM, VM.Record> vm = getControlDomain(conn);
VM dom0 = vm.first();
Set<VIF> vifs = dom0.getVIFs(conn);
if (vifs.size() != 0) {
for (VIF vif : vifs) {
Map<String, String> otherConfig = vif.getOtherConfig(conn);
if (otherConfig != null) {
String nameLabel = otherConfig.get("nameLabel");
if ((nameLabel != null) && nameLabel.equalsIgnoreCase(vifNameLabel)) {
dom0vif = vif;
}
}
}
}
/* create temp VIF0 */
if (dom0vif == null) {
s_logger.debug("Can't find a vif on dom0 for " + networkDesc + ", creating a new one");
VIF.Record vifr = new VIF.Record();
vifr.VM = dom0;
vifr.device = getLowestAvailableVIFDeviceNum(conn, dom0);
if (vifr.device == null) {
s_logger.debug("Failed to create " + networkDesc + ", no vif available");
return;
}
Map<String, String> config = new HashMap<String, String>();
config.put("nameLabel", vifNameLabel);
vifr.otherConfig = config;
vifr.MAC = "FE:FF:FF:FF:FF:FF";
vifr.network = nw;
dom0vif = VIF.create(conn, vifr);
dom0vif.plug(conn);
} else {
s_logger.debug("already have a vif on dom0 for " + networkDesc);
if (!dom0vif.getCurrentlyAttached(conn)) {
dom0vif.plug(conn);
}
}
}
private Network setupvSwitchNetwork(Connection conn) {
try {
Network vswitchNw = null;
if (_host.vswitchNetwork == null) {
Network.Record rec = new Network.Record();
String nwName = Networks.BroadcastScheme.VSwitch.toString();
Set<Network> networks = Network.getByNameLabel(conn, nwName);
if (networks.size() == 0) {
rec.nameDescription = "vswitch network for " + nwName;
rec.nameLabel = nwName;
vswitchNw = Network.create(conn, rec);
} else {
vswitchNw = networks.iterator().next();
}
enableXenServerNetwork(conn, vswitchNw, "vswitch",
"vswicth network");
_host.vswitchNetwork = vswitchNw.getUuid(conn);
} else {
vswitchNw = Network.getByUuid(conn, _host.vswitchNetwork);
enableXenServerNetwork(conn, vswitchNw, "vswitch",
"vswicth network");
}
return vswitchNw;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
protected Network getNetwork(Connection conn, NicTO nic) throws XenAPIException, XmlRpcException {
Pair<Network, String> network = getNativeNetworkForTraffic(conn, nic.getType());
if (nic.getBroadcastUri() != null && nic.getBroadcastUri().toString().contains("untagged")) {
@ -477,7 +570,9 @@ public abstract class CitrixResourceBase implements ServerResource {
return enableVlanNetwork(conn, vlan, network.first(), network.second());
} else if (nic.getBroadcastType() == BroadcastDomainType.Native || nic.getBroadcastType() == BroadcastDomainType.LinkLocal) {
return network.first();
}
} else if (nic.getBroadcastType() == BroadcastDomainType.Vswitch) {
return setupvSwitchNetwork(conn);
}
throw new CloudRuntimeException("Unable to support this type of network broadcast domain: " + nic.getBroadcastUri());
}
@ -3725,6 +3820,78 @@ public abstract class CitrixResourceBase implements ServerResource {
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) {
Connection conn = getConnection();
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();
Network nw = getNetworkByName(conn, nwName);
assert nw!= null : "Why there is no vswith network ???";
String bridge = nw.getBridge(conn);
/*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
* plugin side
*/
for (VIF vif : vifs) {
String vifName = "vif" + domId + vif.getDevice(conn);
String result = callHostPlugin(conn, "vmops", "vlanRemapUtils", "op", "createFlow", "bridge",
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")) {
return new Answer(cmd, true, "Set flow for " + cmd.getVmName()
+ " success, vlans:" + cmd.getVlans());
} else {
return new Answer(cmd, false, "Set flow for " + cmd.getVmName()
+ " failed, vlans:" + cmd.getVlans());
}
*/
return new Answer(cmd, true, "Set flow for " + cmd.getVmName()
+ " success, vlans:" + cmd.getVlans());
} catch (Exception e) {
e.printStackTrace();
}
return new Answer(cmd, false, "Set flow for " + cmd.getVmName()
+ " failed, vlans:" + cmd.getVlans());
}
private Answer execute(OvsCreateGreTunnelCommand cmd) {
Connection conn = getConnection();
try {
String nwName = Networks.BroadcastScheme.VSwitch.toString();
Network nw = getNetworkByName(conn, nwName);
if (nw == null) {
nw = setupvSwitchNetwork(conn);
}
String result = callHostPlugin(conn, "vmops", "vlanRemapUtils",
"op", "createGRE", "bridge", nw.getBridge(conn),
"remoteIP", cmd.getRemoteIp(), "greKey", cmd.getKey());
if (result.equalsIgnoreCase("SUCCESS")) {
return new Answer(cmd, true, "create gre tunnel to "
+ cmd.getRemoteIp() + " success");
} else {
return new Answer(cmd, false, "create gre tunnel to "
+ cmd.getRemoteIp() + " failed");
}
} catch (Exception e) {
e.printStackTrace();
}
return new Answer(cmd, false, "create gre tunnel to " + cmd.getRemoteIp() + " failed");
}
private Answer execute(SecurityIngressRulesCmd cmd) {
Connection conn = getConnection();
if (s_logger.isTraceEnabled()) {
@ -5501,6 +5668,7 @@ public abstract class CitrixResourceBase implements ServerResource {
public String publicNetwork;
public String privateNetwork;
public String linkLocalNetwork;
public String vswitchNetwork;
public String storageNetwork1;
public String storageNetwork2;
public String guestNetwork;

View File

@ -0,0 +1,483 @@
#!/usr/bin/python
# Create flows on Open vSwitch
#
# @param: bridge name, refer to a network created by xenserver
# @param: our MAC
# @param: vlan ID
import os
import sys
from os.path import exists as _exists
from time import localtime as _localtime, asctime as _asctime
vSwitchDBPidFile = "/var/run/openvswitch/ovsdb-server.pid"
vSwitchDBDaemonName = "ovsdb-server"
vSwitchPidFile = "/var/run/openvswitch/ovs-vswitchd.pid"
vsctlPath = "/usr/bin/ovs-vsctl"
vSwitchDaemonName = "ovs-vswitchd"
logFile = "/var/log/cloud/management/vlanRemapUtils.log"
fLog = None
global result
errors = \
{"NO_DB_PID_FILE" : "NO_DB_PID_FILE", \
"DB_NOT_RUN" : "DB_NOT_RUN", \
"NO_SWITCH_PID_FILE" : "NO_SWITCH_PID_FILE", \
"SWITCH_NOT_RUN" : "SWITCH_NOT_RUN", \
"NO_VSCTL" : "NO_VSCTL", \
"COMMAND_FAILED" : "COMMAND_FAILED", \
"ERR_ARGS_NUM" : "ERR_ARGS_NUM", \
"ERROR_OP" : "ERROR_OP", \
"SUCCESS" : "SUCCESS", \
}
def openLog ():
global fLog
try:
if fLog == None:
fLog = open (logFile, "a")
except IOError, e:
#print e
pass
def log (str):
global fLog
if fLog != None:
str = "[%s]:" % _asctime (_localtime()) + str + "\n"
fLog.write (str)
def closeLog ():
global fLog
if fLog != None:
fLog.close ()
def isProcessRun (pidFile, name):
try:
fpid = open (pidFile, "r")
pid = fpid.readline ()
fpid.close ()
except IOError, e:
return -1
pid = pid[:-1]
ps = os.popen ("ps -ae")
for l in ps:
if pid in l and name in l:
ps.close ()
return 0
ps.close ()
return -2
def isToolExist (name):
if _exists (name):
return 0
return -1
def checkvSwitch ():
global result
ret = isProcessRun (vSwitchDBPidFile, vSwitchDBDaemonName);
if ret < 0:
if ret == -1: result = errors["NO_DB_PID_FILE"]
if ret == -2: result = errors["DB_NOT_RUN"]
return -1
ret = isProcessRun (vSwitchPidFile, vSwitchDaemonName)
if ret < 0:
if ret == -1: result = errors["NO_SWITCH_PID_FILE"]
if ret == -2: result = errors["SWITCH_NOT_RUN"]
return -1
if isToolExist (vsctlPath) < 0:
result = errors["NO_VSCTL"]
return -1
return 0
def doCmd (cmds, lines=False):
cmd = ""
for i in cmds:
cmd += " "
cmd += i
log ("do command '%s'" % cmd)
f = os.popen (cmd)
if lines == True:
res = f.readlines ()
else:
res = f.readline ()
res = res[:-1]
f.close ()
if lines == False:
log ("command output '%s'" % res)
return res
######################## GRE creation utils ##########################
# UUID's format is 8-4-4-4-12
def isUUID (uuid):
list = uuid.split ("-")
if len (list) != 5:
return -1
if len (list[0]) != 8 or len (list[1]) != 4 \
or len (list[2]) != 4 or len (list[3]) != 4 \
or len (list[4]) != 12:
return -1
return 0
#FIXME: better check method
def checkGREInterface (bridge, remoteIP, greKey):
listIfaces = [vsctlPath, "list interface"]
res = doCmd (listIfaces, True)
start = False
num = 0
keyStr = "key=%s" % greKey
uuid = ''
for i in res:
if "_uuid" in i:
(x, uuid) = i.split(":")
uuid = strip(uuid)
if "options" in i and remoteIP in i and keyStr in i:
log("WARNING: GRE tunnel for remote_ip=%s key=%s already here" % \
(remoteIP, greKey))
return -1
return 0
def createGRE (bridge, remoteIP, greKey):
global result
name = "%sgre" % bridge
if checkGREInterface(bridge, remoteIP, greKey) < 0:
return 0
createInterface = [vsctlPath, "create interface", "name=%s" % name, \
'type=gre options:"remote_ip=%s key=%s"' % (remoteIP, greKey)]
ifaceUUID = doCmd (createInterface)
if isUUID (ifaceUUID) < 0:
result = errors["COMMAND_FAILED"];
return -1
createPort = [vsctlPath, "create port", "name=%s" % name, \
"interfaces=[%s]" % ifaceUUID]
portUUID = doCmd (createPort)
if isUUID (portUUID) < 0:
result = errors["COMMAND_FAILED"];
return -1
addBridge = [vsctlPath, "add bridge %s" % bridge, "port %s" % portUUID]
doCmd (addBridge)
return 0
######################## End GRE creation utils ##########################
######################## Flow creation utils ##########################
def getPortsOnBridge(bridge):
listBr = [vsctlPath, "list br", bridge]
res = doCmd(listBr, True)
for i in res:
if "ports" in i:
(x, str) = i.split(":")
str = str.lstrip().rstrip()
str = str[1:]
str = str[:-1]
return str.split(",")
return None
def getFieldOfPort(nameOruuid, field):
listport = [vsctlPath, "list port", nameOruuid]
res = doCmd(listport, True)
for i in res:
if field in i:
(x, r) = i.split(":")
return r.lstrip().rstrip()
return None
def getFieldOfInterface(nameOruuid, field):
listIface = [vsctlPath, "list interface", nameOruuid]
res = doCmd(listIface, True)
for i in res:
if field in i:
(x, r) = i.split(":")
return r.lstrip().rstrip()
return None
def strip(str, direction="default"):
str = str.lstrip().rstrip()
if direction == "left":
return str[1:]
if direction == "right":
return str[:-1]
if direction == "both":
str = str[1:]
str = str[:-1]
return str
return str
def getVifPort(bridge, vifName):
portUuids = getPortsOnBridge(bridge)
if portUuids == None:
log("No ports on bridge %s" % bridge)
return -1
for i in portUuids:
name = getFieldOfPort(i, "name")
if name == None:
log("WARNING: no name found for %s" % name)
continue
name = strip(name, "both")
if name == vifName:
return getFieldOfInterface(vifName, "ofport")
return None
def getInterfacesOnPort(nameOruuid):
listPort = [vsctlPath, "list port", nameOruuid]
res = doCmd(listPort, True)
for i in res:
if "interfaces" in i:
(x, str) = i.split(":")
str = strip(str, "both")
return str.split(",")
return None
def getOfPortsByType(bridge, askGre):
portUuids = getPortsOnBridge(bridge)
if portUuids == None:
log("WARNING:No ports on bridge %s" % bridge)
return -1
OfPorts = []
for i in portUuids:
ifaces = getInterfacesOnPort(i)
if ifaces == None:
log("WARNING:No interfaces on port %s" % i)
continue
for j in ifaces:
if j == '[]':
log("WARNING:invalid interface [] on port %s" % i)
continue
type = getFieldOfInterface(j, "type")
type = strip(type)
if askGre == True and type == "gre":
ofport = getFieldOfInterface(j, "ofport")
if ofport != '[]':OfPorts.append(strip(ofport))
elif askGre == False and type != "gre":
ofport = getFieldOfInterface(j, "ofport")
if ofport != '[]' and ofport != "65534":OfPorts.append(strip(ofport))
return OfPorts
def getNoneGreOfPort(bridge):
return getOfPortsByType(bridge, False)
def getGreOfPorts(bridge):
return getOfPortsByType(bridge, True)
def findInPort():
listIface = [vsctlPath, "list interface"]
res = doCmd (listIface, True)
inport = []
port = ""
for i in res:
if "ofport" in i:
(x, port) = i.split(":")
port = port.lstrip().rstrip()
if "type" in i:
(x, type) = i.split(":")
type = type.lstrip().rstrip()
if type == "gre":
inport.append (port)
return inport
def formatFlow(inPort, vlan, mac, outPut):
flow = "in_port=%s dl_vlan=%s dl_dst=%s idle_timeout=0 hard_timeout=0 \
actions=strip_vlan,output:%s" % (inPort, vlan, mac, outPut)
return flow
def delFlow(mac):
param = "dl_dst=%s" % mac
delFlow = ["ovs-ofctl del-flows %s" % bridge, '"%s"' % param]
doCmd(delFlow)
def delARPFlow(vlan):
param = "dl_type=0x0806 dl_vlan=%s" % vlan
delFlow = ["ovs-ofctl del-flows %s" % bridge, '"%s"' % param]
doCmd(delFlow)
def formatARPFlow(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=0x0806 idle_timeout=0 hard_timeout=0 \
actions=strip_vlan,%s" % (inPort, vlan, outputs)
return flow
def createFlow (bridge, vifName, mac, ip, vlan, remap):
inport = getGreOfPorts(bridge)
if len(inport) == 0:
log("WARNING: no inport found")
return -1
output = getVifPort(bridge, vifName)
if output == None:
log("WARNING: cannot find ofport for %s" % vifName)
return -1
if output == '[]':
log("WARNING: ofport is [] for %s" % vifName)
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, "both")
log("")
log("Create flow for remap")
noneGreOfPorts = getNoneGreOfPort(bridge)
isARP = True
if len(noneGreOfPorts) == 0:
log("WARNING: no none GRE ofports found, no ARP flow will be created")
isARP = False
for j in remap.split(","):
delARPFlow(j)
for i in inport:
flow = formatFlow(i, j, mac, output)
param = bridge + ' "%s"' % flow
addflow = ["ovs-ofctl add-flow", param]
doCmd (addflow)
if isARP == True:
flow = formatARPFlow(bridge, i, j, noneGreOfPorts)
param = bridge + ' "%s"' % flow
addflow = ["ovs-ofctl add-flow", param]
doCmd (addflow)
return 0
######################## End Flow creation utils ##########################
def setTag(vifName, vlan):
log("")
log("Set tag")
setTagCmd = [vsctlPath, "set port", vifName, "tag=%s"%vlan]
doCmd (setTagCmd)
return 0
def doCreateGRE(bridge, remoteIP, key):
if createGRE(bridge, remoteIP, key) < 0:
log("WARNING: create GRE tunnel on %s for %s failed" % (bridge, \
remoteIP))
else:
log("WARNING: create GRE tunnel on %s for %s success" % (bridge, \
remoteIP))
def doCreateFlow (bridge, vifName, mac, ip, vlan, remap):
setTag (vifName, vlan)
if createFlow(bridge, vifName, mac, ip, vlan, remap) < 0:
log ("Create flow failed(bridge=%s, vifName=%s, mac=%s, ip=%s, vlan=%s,\
remap=%s" % (bridge, vifName, mac, ip, vlan, remap))
else:
log ("Create flow success(bridge=%s, vifName=%s, mac=%s, ip=%s, vlan=%s,\
remap=%s" % (bridge, vifName, mac, ip, vlan, remap))
def doDeleteFlow(bridge, vifName, mac, remap):
delFlow(mac)
log("Delete flows for %s" % mac)
remap = strip(remap, "both")
# remove our port from arp flow
inport = getGreOfPorts(bridge)
if len(inport) == 0:
return
mine = getVifPort(bridge, vifName)
noneGreOfPorts = getNoneGreOfPort(bridge)
noneGreOfPorts.remove(mine)
log("Delete ARP flows for(vifname=%s, ofport=%s)" % (vifName, mine))
for j in remap.split(","):
delARPFlow(j)
for i in inport:
flow = formatARPFlow(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"]
print result
log ("Error number of arguments")
sys.exit (-1)
if __name__ == "__main__":
global result
openLog ()
if checkvSwitch () < 0:
print result
log ("Check switch failed, reason = '%s'" % result)
sys.exit (-1)
op = sys.argv[1]
if op == "createGRE":
checkArgNum(5)
bridge = sys.argv[2]
remoteIP = sys.argv[3]
key = sys.argv[4]
doCreateGRE(bridge, remoteIP, key)
elif op == "createFlow":
checkArgNum(8)
bridge = sys.argv[2]
vifName = sys.argv[3]
mac = sys.argv[4]
vlan = sys.argv[5]
remap = sys.argv[6]
ip = sys.argv[7]
doCreateFlow(bridge, vifName, mac, ip, vlan, remap)
elif op == "deleteFlow":
checkArgNum(6)
bridge = sys.argv[2]
vifName = sys.argv[3]
mac = sys.argv[4]
remap = sys.argv[5]
doDeleteFlow(bridge, vifName, mac, remap)
else:
log("WARNING: get an unkown op %s" % op)
result=errors["ERROR_OP"]
print result
sys.exit(-1)
result = errors["SUCCESS"]
closeLog ()
print result

View File

@ -128,6 +128,39 @@ def ipassoc(session, args):
return txt
@echo
def vlanRemapUtils(session, args):
cmd = []
cmd.insert(0, "python")
cmd.insert(1, "/opt/xensource/bin/vlanRemapUtils.py")
op = args.pop("op")
cmd.insert(2, op)
if op == "createGRE":
cmd.insert(3, args.pop("bridge"))
cmd.insert(4, args.pop("remoteIP"))
cmd.insert(5, args.pop("greKey"))
elif op == "createFlow":
cmd.insert(3, args.pop("bridge"))
cmd.insert(4, args.pop("vifName"))
cmd.insert(5, args.pop("mac"))
cmd.insert(6, args.pop("vlan"))
cmd.insert(7, args.pop("remap"))
cmd.insert(8, args.pop("ip"))
elif op == "deleteFlow":
cmd.insert(3, args.pop("bridge"))
cmd.insert(4, args.pop("vifName"))
cmd.insert(5, args.pop("mac"))
cmd.insert(6, args.pop("remap"))
try:
txt = util.pread2(cmd)
except:
util.SMlog("vlanRemapUtils failed")
txt = 'failed'
return txt
@echo
def vm_data(session, args):
router_ip = args.pop('routerIP')
@ -519,7 +552,6 @@ def default_ebtables_rules(vm_name, vif, vm_ip, vm_mac):
util.SMlog("Failed to program default ebtables OUT rules")
return 'false'
@echo
def default_network_rules_systemvm(session, args):
vm_name = args.pop('vmName')
@ -1032,5 +1064,5 @@ def network_rules(session, args):
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, "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, "vlanRemapUtils":vlanRemapUtils,"cleanup_rules":cleanup_rules})

View File

@ -60,6 +60,10 @@ public class Commands {
addCommand(null, cmd);
}
public void addCommand(int index, Command cmd) {
_cmds.add(index, cmd);
}
public Answer getAnswer(String id) {
int i = _ids.indexOf(id);
return i == -1 ? null : _answers[i];

View File

@ -60,6 +60,7 @@ public enum Config {
NetworkThrottlingRate("Network", ManagementServer.class, Integer.class, "network.throttling.rate", "200", "Default data transfer rate in megabits per second allowed.", null),
GuestDomainSuffix("Network", AgentManager.class, String.class, "guest.domain.suffix", "cloud-test.cloud.internal", "Default domain name for vms inside virtualized networks fronted by router", null),
DirectNetworkNoDefaultRoute("Network", ManagementServer.class, Boolean.class, "direct.network.no.default.route", "false", "Direct Network Dhcp Server should not send a default route", "true/false"),
OvsNetwork("Network", ManagementServer.class, Boolean.class, "open.vswitch.network", "true", "enable/disable open vswitch network", null),
//VPN
RemoteAccessVpnPskLength("Network", AgentManager.class, Integer.class, "remote.access.vpn.psk.length", "24", "The length of the ipsec preshared key (minimum 8, maximum 256)", null),

View File

@ -72,6 +72,9 @@ import com.cloud.network.dao.NetworkRuleConfigDaoImpl;
import com.cloud.network.dao.RemoteAccessVpnDaoImpl;
import com.cloud.network.dao.VpnUserDaoImpl;
import com.cloud.network.lb.LoadBalancingRulesManagerImpl;
import com.cloud.network.ovs.OvsNetworkManagerImpl;
import com.cloud.network.ovs.dao.VlanMappingDaoImpl;
import com.cloud.network.ovs.dao.VlanMappingDirtyDaoImpl;
import com.cloud.network.router.VirtualNetworkApplianceManagerImpl;
import com.cloud.network.rules.RulesManagerImpl;
import com.cloud.network.rules.dao.PortForwardingRulesDaoImpl;
@ -236,6 +239,8 @@ public class DefaultComponentLibrary implements ComponentLibrary {
addDao("PortForwardingRulesDao", PortForwardingRulesDaoImpl.class);
addDao("UsageEventDao", UsageEventDaoImpl.class);
addDao("ClusterDetailsDao", ClusterDetailsDaoImpl.class);
addDao("VlanMappingDao", VlanMappingDaoImpl.class);
addDao("VlanMappingDirtyDao", VlanMappingDirtyDaoImpl.class);
}
Map<String, ComponentInfo<Manager>> _managers = new HashMap<String, ComponentInfo<Manager>>();
@ -290,6 +295,7 @@ public class DefaultComponentLibrary implements ComponentLibrary {
addManager("LoadBalancingRulesManager", LoadBalancingRulesManagerImpl.class);
addManager("RulesManager", RulesManagerImpl.class);
addManager("RemoteAccessVpnManager", RemoteAccessVpnManagerImpl.class);
addManager("OvsNetworkManager", OvsNetworkManagerImpl.class);
}
protected <T> List<ComponentInfo<Adapter>> addAdapterChain(Class<T> interphace, List<Pair<String, Class<? extends T>>> adapters) {

View File

@ -0,0 +1,94 @@
package com.cloud.network.element;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import com.cloud.deploy.DeployDestination;
import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network;
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.ovs.OvsNetworkManager;
import com.cloud.network.rules.FirewallRule;
import com.cloud.offering.NetworkOffering;
import com.cloud.utils.component.AdapterBase;
import com.cloud.utils.component.Inject;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
@Local(value=NetworkElement.class)
public class OvsElement extends AdapterBase implements NetworkElement {
@Inject OvsNetworkManager _ovsNetworkMgr;
@Override
public Map<Service, Map<Capability, String>> getCapabilities() {
// TODO Auto-generated method stub
return null;
}
@Override
public Provider getProvider() {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean implement(Network network, NetworkOffering offering,
DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException,
InsufficientCapacityException {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean prepare(Network network, NicProfile nic,
VirtualMachineProfile<? extends VirtualMachine> vm,
DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException,
InsufficientCapacityException {
_ovsNetworkMgr.CheckAndUpdateDhcpFlow(network);
return true;
}
@Override
public boolean release(Network network, NicProfile nic,
VirtualMachineProfile<? extends VirtualMachine> vm,
ReservationContext context) throws ConcurrentOperationException,
ResourceUnavailableException {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean shutdown(Network network, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean applyIps(Network network,
List<? extends PublicIpAddress> ipAddress)
throws ResourceUnavailableException {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean applyRules(Network network,
List<? extends FirewallRule> rules)
throws ResourceUnavailableException {
// TODO Auto-generated method stub
return true;
}
}

View File

@ -0,0 +1,27 @@
package com.cloud.network.ovs;
import com.cloud.agent.manager.Commands;
import com.cloud.deploy.DeployDestination;
import com.cloud.network.Network;
import com.cloud.uservm.UserVm;
import com.cloud.utils.component.Manager;
import com.cloud.vm.State;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachineProfile;
public interface OvsNetworkManager extends Manager {
public boolean isOvsNetworkEnabled();
public long askVlanId(long accountId, long hostId);
public String getVlanMapping(long accountId);
public void CheckAndCreateTunnel(Commands cmds,
VirtualMachineProfile<UserVmVO> profile, DeployDestination dest);
public void applyDefaultFlow(Commands cmds,
VirtualMachineProfile<UserVmVO> profile, DeployDestination dest);
public void CheckAndUpdateDhcpFlow(Network nw);
public void handleVmStateTransition(UserVm userVm, State vmState);
}

View File

@ -0,0 +1,304 @@
package com.cloud.network.ovs;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.ejb.Local;
import javax.naming.ConfigurationException;
import org.apache.log4j.Logger;
import com.cloud.agent.AgentManager;
import com.cloud.agent.manager.Commands;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.deploy.DeployDestination;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
import com.cloud.network.Network;
import com.cloud.network.NetworkVO;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.ovs.dao.VlanMappingDao;
import com.cloud.network.ovs.dao.VlanMappingDirtyDao;
import com.cloud.network.ovs.dao.VlanMappingVO;
import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair;
import com.cloud.utils.component.Inject;
import com.cloud.utils.db.Transaction;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.NicVO;
import com.cloud.vm.State;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.DomainRouterDao;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
@Local(value={OvsNetworkManager.class})
public class OvsNetworkManagerImpl implements OvsNetworkManager {
private static final Logger s_logger = Logger.getLogger(OvsNetworkManagerImpl.class);
@Inject ConfigurationDao _configDao;
@Inject VlanMappingDao _vlanMappingDao;
@Inject UserVmDao _userVmDao;
@Inject HostDao _hostDao;
@Inject AgentManager _agentMgr;
@Inject NicDao _nicDao;
@Inject NetworkDao _networkDao;
@Inject VlanMappingDirtyDao _vlanMappingDirtyDao;
@Inject DomainRouterDao _routerDao;
String _name;
boolean _isEnabled;
@Override
public boolean configure(String name, Map<String, Object> params)
throws ConfigurationException {
_name = name;
_isEnabled = _configDao.getValue(Config.OvsNetwork.key()).equalsIgnoreCase("true") ? true : false;
return true;
}
@Override
public boolean start() {
// TODO Auto-generated method stub
return true;
}
@Override
public boolean stop() {
// TODO Auto-generated method stub
return true;
}
@Override
public String getName() {
// TODO Auto-generated method stub
return _name;
}
@Override
public boolean isOvsNetworkEnabled() {
// TODO Auto-generated method stub
return _isEnabled;
}
@Override
public long askVlanId(long accountId, long hostId) {
assert _isEnabled : "Who call me ??? while OvsNetwokr is not enabled!!!";
final Transaction txn = Transaction.currentTxn();
txn.start();
List<VlanMappingVO> mappings = _vlanMappingDao.listByAccountIdAndHostId(accountId, hostId);
long vlan = 0;
if (mappings.size() !=0) {
assert mappings.size() == 1 : "We should only have one vlan for an account on a host";
txn.commit();
vlan = mappings.get(0).getVlan();
s_logger.debug("Already has an Vlan " + vlan + " on host " + hostId
+ " for account " + accountId + ", use it!");
return vlan;
}
mappings = _vlanMappingDao.listByHostId(hostId);
if (mappings.size() > 0) {
ArrayList<Long> vlans = new ArrayList<Long>();
for (VlanMappingVO vo : mappings) {
vlans.add(new Long(vo.getVlan()));
}
// Find first available vlan
int i;
for (i=0; i<4096; i++) {
if (!vlans.contains(new Long(i))) {
vlan = i;
break;
}
}
assert i!=4096 : "Terrible, vlan exhausted on this server!!!";
}
VlanMappingVO newVlan = new VlanMappingVO(accountId, hostId, vlan);
_vlanMappingDao.persist(newVlan);
_vlanMappingDirtyDao.markDirty(accountId);
txn.commit();
return 0;
}
@Override
public String getVlanMapping(long accountId) {
assert _isEnabled : "Who call me ??? while OvsNetwokr is not enabled!!!";
final Transaction txn = Transaction.currentTxn();
txn.start();
List<VlanMappingVO> ours = _vlanMappingDao.listByAccountId(accountId);
txn.commit();
ArrayList<Long>vlans = new ArrayList<Long>();
for (VlanMappingVO vo : ours) {
vlans.add(new Long(vo.getVlan()));
}
StringBuffer buf = new StringBuffer();
for (Long i : vlans) {
buf.append("/");
buf.append(i.toString());
buf.append("/");
}
return buf.toString();
}
@Override
public void CheckAndCreateTunnel(Commands cmds, VirtualMachineProfile<UserVmVO> profile,
DeployDestination dest) {
if (!_isEnabled) {
return;
}
UserVmVO userVm = profile.getVirtualMachine();
if (userVm.getType() != VirtualMachine.Type.User) {
return;
}
long hostId = dest.getHost().getId();
long accountId = userVm.getAccountId();
List<UserVmVO> vms = _userVmDao.listByAccountIdAndHostId(accountId, hostId);
if (vms.size() != 0) {
s_logger.debug("Already has GRE tunnel for account " + accountId
+ " for host " + hostId);
return;
}
vms = _userVmDao.listByAccountId(accountId);
List<Long>remoteHostIds = new ArrayList<Long>();
for (UserVmVO v : vms) {
Long rh = v.getHostId();
if (rh == null || rh.longValue() == hostId) {
continue;
}
if (!remoteHostIds.contains(rh)) {
remoteHostIds.add(rh);
}
}
try {
String myIp = dest.getHost().getPrivateIpAddress();
for (Long i : remoteHostIds) {
HostVO rHost = _hostDao.findById(i.longValue());
cmds.addCommand(
0, new OvsCreateGreTunnelCommand(rHost.getPrivateIpAddress(), "1"));
_agentMgr.send(i.longValue(), new OvsCreateGreTunnelCommand(myIp, "1"));
s_logger.debug("Ask host " + i.longValue() + " to create gre tunnel to " + hostId);
}
} catch (Exception e) {
e.printStackTrace();
}
}
private String parseVlanAndMapping(String uri) {
String sub = uri.substring(BroadcastDomainType.Vswitch.scheme().length() + "://".length() - 1);
return sub;
}
@Override
public void applyDefaultFlow(Commands cmds,
VirtualMachineProfile<UserVmVO> profile, DeployDestination dest) {
if (!_isEnabled) {
return;
}
UserVmVO userVm = profile.getVirtualMachine();
VirtualMachine.Type vmType = userVm.getType();
if (vmType != VirtualMachine.Type.User
&& vmType != VirtualMachine.Type.DomainRouter) {
return;
}
List<NicVO> nics = _nicDao.listBy(userVm.getId());
if (nics.size() == 0)
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());
cmds.addCommand(new OvsSetTagAndFlowCommand(userVm.getName(), vlans));
}
@Override
public void CheckAndUpdateDhcpFlow(Network nw) {
if (!_isEnabled) {
return;
}
DomainRouterVO router = _routerDao.findByNetworkConfiguration(nw.getId());
if (router == null) {
return;
}
long accountId = nw.getAccountId();
if (!_vlanMappingDirtyDao.isDirty(accountId)) {
return;
}
try {
String vlans = getVlanMapping(accountId);
_agentMgr.send(router.getHostId(), new OvsSetTagAndFlowCommand(
router.getName(), vlans));
s_logger.debug("ask router " + router.getName() + " on host "
+ router.getHostId() + " update vlan map to " + vlans);
} catch (Exception e) {
e.printStackTrace();
}
}
protected void handleVmStarted(UserVm userVm) {
scheduleFlowUpdateToHosts(affectedVms, true, null);
}
protected void handleVmStopped(UserVm userVm) {
scheduleFlowUpdateToHosts(affectedVms, true, null);
}
@Override
public void handleVmStateTransition(UserVm userVm, State vmState) {
if (!_isEnabled) {
return;
}
switch (vmState) {
case Creating:
case Destroyed:
case Error:
case Migrating:
case Expunging:
case Starting:
case Unknown:
return;
case Running:
handleVmStarted(userVm);
break;
case Stopping:
case Stopped:
handleVmStopped(userVm);
break;
}
}
}

View File

@ -0,0 +1,11 @@
package com.cloud.network.ovs.dao;
import java.util.List;
import com.cloud.utils.db.GenericDao;
public interface VlanMappingDao extends GenericDao<VlanMappingVO, Long> {
List<VlanMappingVO> listByAccountIdAndHostId(long accountId, long hostId);
List<VlanMappingVO> listByHostId(long hostId);
List<VlanMappingVO> listByAccountId(long accountId);
}

View File

@ -0,0 +1,50 @@
package com.cloud.network.ovs.dao;
import java.util.List;
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 javax.ejb.Local;
@Local(value = { VlanMappingDao.class })
public class VlanMappingDaoImpl extends GenericDaoBase<VlanMappingVO, Long>
implements VlanMappingDao {
protected final SearchBuilder<VlanMappingVO> AllFieldsSearch;
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();
}
@Override
public List<VlanMappingVO> listByAccountIdAndHostId(long accountId,
long hostId) {
SearchCriteria<VlanMappingVO> sc = AllFieldsSearch.create();
sc.setParameters("account_id", accountId);
sc.setParameters("host_id", hostId);
return listBy(sc, null);
}
@Override
public List<VlanMappingVO> listByHostId(long hostId) {
SearchCriteria<VlanMappingVO> sc = AllFieldsSearch.create();
sc.setParameters("host_id", hostId);
return listBy(sc, null);
}
@Override
public List<VlanMappingVO> listByAccountId(long accountId) {
SearchCriteria<VlanMappingVO> sc = AllFieldsSearch.create();
sc.setParameters("account_id", accountId);
return listBy(sc, null);
}
}

View File

@ -0,0 +1,9 @@
package com.cloud.network.ovs.dao;
import com.cloud.utils.db.GenericDao;
public interface VlanMappingDirtyDao extends GenericDao<VlanMappingDirtyVO, Long> {
public boolean isDirty(long accountId);
public void markDirty(long accountId);
public void clean(long accountId);
}

View File

@ -0,0 +1,62 @@
package com.cloud.network.ovs.dao;
import javax.ejb.Local;
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;
@Local(value = { VlanMappingDirtyDao.class })
public class VlanMappingDirtyDaoImpl extends
GenericDaoBase<VlanMappingDirtyVO, Long> implements VlanMappingDirtyDao {
protected final SearchBuilder<VlanMappingDirtyVO> AllFieldsSearch;
public VlanMappingDirtyDaoImpl() {
super();
AllFieldsSearch = createSearchBuilder();
AllFieldsSearch.and("account_id", AllFieldsSearch.entity().getAccountId(), Op.EQ);
AllFieldsSearch.and("dirty", AllFieldsSearch.entity().isDirty(), Op.EQ);
AllFieldsSearch.done();
}
@Override
public boolean isDirty(long accountId) {
SearchCriteria<VlanMappingDirtyVO> sc = AllFieldsSearch.create();
sc.setParameters("account_id", accountId);
VlanMappingDirtyVO vo = findOneBy(sc);
if (vo == null) {
return false;
}
return vo.isDirty();
}
@Override
public void markDirty(long accountId) {
SearchCriteria<VlanMappingDirtyVO> sc = AllFieldsSearch.create();
sc.setParameters("account_id", accountId);
VlanMappingDirtyVO vo = findOneBy(sc);
if (vo == null) {
vo = new VlanMappingDirtyVO(accountId, true);
persist(vo);
} else {
vo.markDirty();
update(vo, sc);
}
}
@Override
public void clean(long accountId) {
SearchCriteria<VlanMappingDirtyVO> sc = AllFieldsSearch.create();
sc.setParameters("account_id", accountId);
VlanMappingDirtyVO vo = findOneBy(sc);
if (vo == null) {
vo = new VlanMappingDirtyVO(accountId, false);
persist(vo);
} else {
vo.clean();
update(vo, sc);
}
}
}

View File

@ -0,0 +1,52 @@
package com.cloud.network.ovs.dao;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name=("ovs_vlan_mapping_dirty"))
public class VlanMappingDirtyVO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "dirty")
private boolean dirty;
@Column(name = "account_id")
private long accountId;
public VlanMappingDirtyVO() {
}
public VlanMappingDirtyVO(long accountId, boolean dirty) {
this.accountId = accountId;
this.dirty = dirty;
}
public long getId() {
return id;
}
public long getAccountId() {
return accountId;
}
public boolean isDirty() {
return dirty;
}
public void markDirty() {
dirty = true;
}
public void clean() {
dirty = false;
}
}

View File

@ -0,0 +1,52 @@
package com.cloud.network.ovs.dao;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Column;
@Entity
@Table(name=("ovs_host_vlan_alloc"))
public class VlanMappingVO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;
@Column(name = "host_id")
private long hostId;
@Column(name = "account_id")
private long accountId;
@Column(name = "vlan")
private long vlan;
public VlanMappingVO(long accountId, long hostId, long vlan) {
this.hostId = hostId;
this.accountId = accountId;
this.vlan = vlan;
}
public VlanMappingVO() {
}
public long getHostId() {
return hostId;
}
public long getAccountId() {
return accountId;
}
public long getVlan() {
return vlan;
}
public long getId() {
return id;
}
}

View File

@ -129,6 +129,7 @@ import com.cloud.network.dao.LoadBalancerDao;
import com.cloud.network.dao.LoadBalancerVMMapDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.lb.LoadBalancingRulesManager;
import com.cloud.network.ovs.OvsNetworkManager;
import com.cloud.network.router.VirtualNetworkApplianceManager;
import com.cloud.network.rules.RulesManager;
import com.cloud.network.security.SecurityGroupManager;
@ -258,6 +259,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
@Inject RulesManager _rulesMgr;
@Inject LoadBalancingRulesManager _lbMgr;
@Inject UsageEventDao _usageEventDao;
@Inject OvsNetworkManager _ovsNetworkMgr;
private IpAddrAllocator _IpAllocator;
ScheduledExecutorService _executor = null;
@ -2395,6 +2397,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
}
_vmDao.update(userVm.getId(), userVm);
_ovsNetworkMgr.CheckAndCreateTunnel(cmds, profile, dest);
return true;
}

View File

@ -100,4 +100,5 @@ public interface UserVmDao extends GenericDao<UserVmVO, Long>, StateDao<State, V
UserVm findByZoneAndAcctAndGuestIpAddress(long zoneId, long accountId, String ipAddress);
UserVm findVmByZoneIdAndName(long zoneId, String name);
List<UserVmVO> listByAccountIdAndHostId(long accountId, long hostId);
}

View File

@ -57,6 +57,7 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use
protected final SearchBuilder<UserVmVO> GuestIpSearch;
protected final SearchBuilder<UserVmVO> ZoneAccountGuestIpSearch;
protected final SearchBuilder<UserVmVO> ZoneNameSearch;
protected final SearchBuilder<UserVmVO> AccountHostSearch;
protected final SearchBuilder<UserVmVO> DestroySearch;
protected SearchBuilder<UserVmVO> AccountDataCenterVirtualSearch;
@ -136,6 +137,11 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use
ZoneNameSearch.and("dataCenterId", ZoneNameSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
ZoneNameSearch.and("name", ZoneNameSearch.entity().getName(), SearchCriteria.Op.EQ);
ZoneNameSearch.done();
AccountHostSearch = createSearchBuilder();
AccountHostSearch.and("accountId", AccountHostSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
AccountHostSearch.and("hostId", AccountHostSearch.entity().getHostId(), SearchCriteria.Op.EQ);
AccountHostSearch.done();
_updateTimeAttr = _allAttributes.get("updateTime");
assert _updateTimeAttr != null : "Couldn't get this updateTime attribute";
@ -401,4 +407,12 @@ public class UserVmDaoImpl extends GenericDaoBase<UserVmVO, Long> implements Use
sc.setParameters("name", name);
return findOneBy(sc);
}
@Override
public List<UserVmVO> listByAccountIdAndHostId(long accountId, long hostId) {
SearchCriteria<UserVmVO> sc = AccountHostSearch.create();
sc.setParameters("hostId", hostId);
sc.setParameters("accountId", accountId);
return listBy(sc);
}
}

View File

@ -1323,4 +1323,19 @@ CREATE TABLE `cloud`.`usage_event` (
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`ovs_host_vlan_alloc`(
`id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT,
`host_id` bigint unsigned COMMENT 'host id',
`account_id` bigint unsigned COMMENT 'account id',
`vlan` bigint unsigned COMMENT 'vlan id under account #account_id on host #host_id',
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`ovs_vlan_mapping_dirty`(
`id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT,
`account_id` bigint unsigned COMMENT 'account id',
`dirty` int(1) unsigned NOT NULL DEFAULT 0 COMMENT '1 means vlan mapping of this account was changed',
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SET foreign_key_checks = 1;