bug 7722: open vswitch - works at VM start time, need fullsync() and flow clean in next

This commit is contained in:
Frank 2011-01-05 18:05:44 -08:00
parent 5c01c42ba7
commit c94b6acadf
21 changed files with 890 additions and 83 deletions

View File

@ -3820,34 +3820,22 @@ 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
* none guest network nic. don't worry, it will fail silently 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);
}
String result = callHostPlugin(conn, "vmops", "ovs_set_tag_and_flow", "bridge", bridge,
"vmName", cmd.getVmName(), "vlans", cmd.getVlans());
s_logger.debug("set flow for " + cmd.getVmName() + " " + result);
/*
if (result.equalsIgnoreCase("SUCCESS")) {
return new Answer(cmd, true, "Set flow for " + cmd.getVmName()
+ " success, vlans:" + cmd.getVlans());
@ -3855,9 +3843,6 @@ public abstract class CitrixResourceBase implements ServerResource {
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();
}

View File

@ -338,7 +338,7 @@ def formatARPFlow(bridge, inPort, vlan, ports):
actions=strip_vlan,%s" % (inPort, vlan, outputs)
return flow
def createFlow (bridge, vifName, mac, ip, vlan, remap):
def createFlow (bridge, vifName, mac, remap):
inport = getGreOfPorts(bridge)
if len(inport) == 0:
log("WARNING: no inport found")
@ -357,7 +357,7 @@ def createFlow (bridge, vifName, mac, ip, vlan, remap):
delFlow(mac)
#set remap here, remap has format e.g. [1,22,200,13,16]
remap = strip(remap, "both")
remap = strip(remap)
log("")
log("Create flow for remap")
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")
isARP = False
for j in remap.split(","):
for j in remap.split("/"):
delARPFlow(j)
for i in inport:
flow = formatFlow(i, j, mac, output)
@ -383,8 +383,19 @@ def createFlow (bridge, vifName, mac, ip, vlan, remap):
return 0
######################## End Flow creation utils ##########################
def setTag(vifName, vlan):
log("")
def setTag(bridge, vifName, vlan):
# 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")
setTagCmd = [vsctlPath, "set port", vifName, "tag=%s"%vlan]
doCmd (setTagCmd)
@ -398,20 +409,22 @@ def doCreateGRE(bridge, remoteIP, key):
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))
def doCreateFlow (bridge, vifName, mac, remap):
if createFlow(bridge, vifName, mac, remap) < 0:
log ("Create flow failed(bridge=%s, vifName=%s, mac=%s,\
remap=%s" % (bridge, vifName, mac, remap))
else:
log ("Create flow success(bridge=%s, vifName=%s, mac=%s, ip=%s, vlan=%s,\
remap=%s" % (bridge, vifName, mac, ip, vlan, remap))
log ("Create flow success(bridge=%s, vifName=%s, mac=%s,\
remap=%s" % (bridge, vifName, mac, remap))
def doSetTag (bridge, vifName, tag):
setTag(bridge, vifName, tag)
def doDeleteFlow(bridge, vifName, mac, remap):
delFlow(mac)
log("Delete flows for %s" % mac)
remap = strip(remap, "both")
remap = strip(remap)
# remove our port from arp flow
inport = getGreOfPorts(bridge)
@ -423,7 +436,7 @@ def doDeleteFlow(bridge, vifName, mac, remap):
noneGreOfPorts.remove(mine)
log("Delete ARP flows for(vifname=%s, ofport=%s)" % (vifName, mine))
for j in remap.split(","):
for j in remap.split("/"):
delARPFlow(j)
for i in inport:
flow = formatARPFlow(bridge, i, j, noneGreOfPorts)
@ -457,14 +470,12 @@ if __name__ == "__main__":
key = sys.argv[4]
doCreateGRE(bridge, remoteIP, key)
elif op == "createFlow":
checkArgNum(8)
checkArgNum(6)
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)
remap = sys.argv[5]
doCreateFlow(bridge, vifName, mac, remap)
elif op == "deleteFlow":
checkArgNum(6)
bridge = sys.argv[2]
@ -472,6 +483,12 @@ if __name__ == "__main__":
mac = sys.argv[4]
remap = sys.argv[5]
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:
log("WARNING: get an unkown op %s" % op)
result=errors["ERROR_OP"]

View File

@ -144,14 +144,16 @@ def vlanRemapUtils(session, args):
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"))
elif op == "setTag":
cmd.insert(3, args.pop("bridge"))
cmd.insert(4, args.pop("vifName"))
cmd.insert(5, args.pop("tag"))
try:
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")
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
def default_network_rules_systemvm(session, args):
vm_name = args.pop('vmName')
@ -627,9 +670,9 @@ def default_network_rules(session, args):
vifs = [vif]
try:
util.pread2(['ifconfig', tap])
vifs.append(tap)
vifs.append(tap)
except:
pass
pass
delete_rules_for_vm_in_bridge_firewall_chain(vm_name)
@ -669,7 +712,7 @@ def default_network_rules(session, args):
return 'false'
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:
util.SMlog("Failed to log default network rules, ignoring")
@ -983,9 +1026,9 @@ def network_rules(session, args):
vifs = [vif]
try:
util.pread2(['ifconfig', tap])
vifs.append(tap)
vifs.append(tap)
except:
pass
pass
vm_name = '-'.join(vm_name.split('-')[:-1])
vmchain = vm_name
@ -1064,5 +1107,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, "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})

View File

@ -31,3 +31,4 @@ call_firewall.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
cloud-setup-bonding.sh=..,0755,/opt/xensource/bin
vlanRemapUtils.py=..,0755,/opt/xensource/bin

View File

@ -73,8 +73,10 @@ 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.OvsWorkDaoImpl;
import com.cloud.network.ovs.dao.VlanMappingDaoImpl;
import com.cloud.network.ovs.dao.VlanMappingDirtyDaoImpl;
import com.cloud.network.ovs.dao.VmFlowLogDaoImpl;
import com.cloud.network.router.VirtualNetworkApplianceManagerImpl;
import com.cloud.network.rules.RulesManagerImpl;
import com.cloud.network.rules.dao.PortForwardingRulesDaoImpl;
@ -241,6 +243,8 @@ public class DefaultComponentLibrary implements ComponentLibrary {
addDao("ClusterDetailsDao", ClusterDetailsDaoImpl.class);
addDao("VlanMappingDao", VlanMappingDaoImpl.class);
addDao("VlanMappingDirtyDao", VlanMappingDirtyDaoImpl.class);
addDao("OvsWorkDao", OvsWorkDaoImpl.class);
addDao("VmFlowLogDao", VmFlowLogDaoImpl.class);
}
Map<String, ComponentInfo<Manager>> _managers = new HashMap<String, ComponentInfo<Manager>>();

View File

@ -252,6 +252,7 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
@Override
@DB
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?";

View File

@ -10,6 +10,7 @@ import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.network.Network;
import com.cloud.network.Networks;
import com.cloud.network.PublicIpAddress;
import com.cloud.network.Network.Capability;
import com.cloud.network.Network.Provider;
@ -55,7 +56,15 @@ public class OvsElement extends AdapterBase implements NetworkElement {
DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException,
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;
}

View File

@ -5,6 +5,7 @@ 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.DomainRouterVO;
import com.cloud.vm.State;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VirtualMachineProfile;
@ -16,12 +17,21 @@ public interface OvsNetworkManager extends Manager {
public String getVlanMapping(long accountId);
public void CheckAndCreateTunnel(Commands cmds,
public void UserVmCheckAndCreateTunnel(Commands cmds,
VirtualMachineProfile<UserVmVO> profile, DeployDestination dest);
public void applyDefaultFlow(Commands cmds,
public void applyDefaultFlowToUserVm(Commands cmds,
VirtualMachineProfile<UserVmVO> profile, DeployDestination dest);
public void applyDefaultFlowToRouter(Commands cmds,
VirtualMachineProfile<DomainRouterVO> profile,
DeployDestination dest);
public void CheckAndUpdateDhcpFlow(Network nw);
public void handleVmStateTransition(UserVm userVm, State vmState);
public void RouterCheckAndCreateTunnel(Commands cmds,
VirtualMachineProfile<DomainRouterVO> profile,
DeployDestination dest);
}

View File

@ -1,8 +1,15 @@
package com.cloud.network.ovs;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
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.naming.ConfigurationException;
@ -13,6 +20,7 @@ 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.exception.AgentUnavailableException;
import com.cloud.host.HostVO;
import com.cloud.host.dao.HostDao;
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.TrafficType;
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.VlanMappingDirtyDao;
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.utils.Pair;
import com.cloud.utils.component.ComponentLocator;
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.vm.DomainRouterVO;
import com.cloud.vm.NicVO;
import com.cloud.vm.State;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.dao.DomainRouterDao;
@ -49,61 +67,183 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
@Inject NetworkDao _networkDao;
@Inject VlanMappingDirtyDao _vlanMappingDirtyDao;
@Inject DomainRouterDao _routerDao;
@Inject OvsWorkDao _workDao;
@Inject VmFlowLogDao _flowLogDao;
@Inject UserVmDao _userVMDao;
String _name;
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
public boolean configure(String name, Map<String, Object> params)
throws ConfigurationException {
_name = name;
_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;
}
@Override
public boolean start() {
// TODO Auto-generated method stub
if (_isEnabled) {
_cleanupExecutor.scheduleAtFixedRate(new CleanupThread(), _timeBetweenCleanups, _timeBetweenCleanups, TimeUnit.SECONDS);
}
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;
}
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
@DB
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);
VlanMappingVO currVlan = _vlanMappingDao.findByAccountIdAndHostId(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();
if (currVlan != null) {
vlan = currVlan.getVlan();
currVlan.ref();
_vlanMappingDao.update(currVlan.getId(), currVlan);
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;
}
mappings = _vlanMappingDao.listByHostId(hostId);
List<VlanMappingVO>mappings = _vlanMappingDao.listByHostId(hostId);
if (mappings.size() > 0) {
ArrayList<Long> vlans = new ArrayList<Long>();
for (VlanMappingVO vo : mappings) {
@ -129,8 +269,9 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
}
@Override
@DB
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();
txn.start();
@ -151,22 +292,21 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
return buf.toString();
}
@Override
public void CheckAndCreateTunnel(Commands cmds, VirtualMachineProfile<UserVmVO> profile,
protected void CheckAndCreateTunnel(Commands cmds, VMInstanceVO instance,
DeployDestination dest) {
if (!_isEnabled) {
return;
}
UserVmVO userVm = profile.getVirtualMachine();
if (userVm.getType() != VirtualMachine.Type.User) {
if (instance.getType() != VirtualMachine.Type.User
&& instance.getType() != VirtualMachine.Type.DomainRouter) {
return;
}
long hostId = dest.getHost().getId();
long accountId = userVm.getAccountId();
long accountId = instance.getAccountId();
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
+ " for host " + hostId);
return;
@ -204,21 +344,19 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
return sub;
}
@Override
public void applyDefaultFlow(Commands cmds,
VirtualMachineProfile<UserVmVO> profile, DeployDestination dest) {
protected void applyDefaultFlow(Commands cmds,
VMInstanceVO instance, DeployDestination dest) {
if (!_isEnabled) {
return;
}
UserVmVO userVm = profile.getVirtualMachine();
VirtualMachine.Type vmType = userVm.getType();
VirtualMachine.Type vmType = instance.getType();
if (vmType != VirtualMachine.Type.User
&& vmType != VirtualMachine.Type.DomainRouter) {
return;
}
List<NicVO> nics = _nicDao.listBy(userVm.getId());
List<NicVO> nics = _nicDao.listBy(instance.getId());
if (nics.size() == 0)
return;
@ -237,7 +375,7 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
assert nic!=null : "Why there is no guest network nic???";
String vlans = parseVlanAndMapping(nic.getBroadcastUri().toASCIIString());
cmds.addCommand(new OvsSetTagAndFlowCommand(userVm.getName(), vlans));
cmds.addCommand(new OvsSetTagAndFlowCommand(instance.getName(), vlans));
}
@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);
}
protected void handleVmStopped(UserVm userVm) {
scheduleFlowUpdateToHosts(affectedVms, true, null);
//TODO: think about lock
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
@ -291,14 +519,42 @@ public class OvsNetworkManagerImpl implements OvsNetworkManager {
case Unknown:
return;
case Running:
handleVmStarted(userVm);
handleVmStateChange(userVm);
break;
case Stopping:
case Stopped:
handleVmStopped(userVm);
checkAndRemove(userVm);
handleVmStateChange(userVm);
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);
}
}

View 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);
}

View 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;
}
}

View 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;
}
}

View File

@ -8,4 +8,5 @@ public interface VlanMappingDao extends GenericDao<VlanMappingVO, Long> {
List<VlanMappingVO> listByAccountIdAndHostId(long accountId, long hostId);
List<VlanMappingVO> listByHostId(long hostId);
List<VlanMappingVO> listByAccountId(long accountId);
VlanMappingVO findByAccountIdAndHostId(long accountId, long hostId);
}

View File

@ -47,4 +47,11 @@ public class VlanMappingDaoImpl extends GenericDaoBase<VlanMappingVO, Long>
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);
}
}

View File

@ -23,11 +23,15 @@ public class VlanMappingVO {
@Column(name = "vlan")
private long vlan;
@Column(name = "ref")
private int ref;
public VlanMappingVO(long accountId, long hostId, long vlan) {
this.hostId = hostId;
this.accountId = accountId;
this.vlan = vlan;
this.ref = 1;
}
public VlanMappingVO() {
@ -49,4 +53,17 @@ public class VlanMappingVO {
public long getId() {
return id;
}
public int getRef() {
return ref;
}
public void ref() {
ref++;
}
public int unref() {
ref--;
return ref;
}
}

View 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);
}

View 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();
}
}

View 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++;
}
}

View File

@ -129,6 +129,7 @@ import com.cloud.network.dao.VpnUserDao;
import com.cloud.network.lb.LoadBalancingRule;
import com.cloud.network.lb.LoadBalancingRule.LbDestination;
import com.cloud.network.lb.LoadBalancingRulesManager;
import com.cloud.network.ovs.OvsNetworkManager;
import com.cloud.network.router.VirtualRouter.Role;
import com.cloud.network.rules.FirewallRule;
import com.cloud.network.rules.PortForwardingRule;
@ -294,6 +295,7 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
RemoteAccessVpnDao _vpnDao;
@Inject
VMInstanceDao _instanceDao;
OvsNetworkManager _ovsNetworkMgr;
long _routerTemplateId = -1;
int _routerRamSize;
@ -1250,6 +1252,9 @@ public class VirtualNetworkApplianceManagerImpl implements VirtualNetworkApplian
@Override
public boolean finalizeDeployment(Commands cmds, VirtualMachineProfile<DomainRouterVO> profile, DeployDestination dest, ReservationContext context) throws ResourceUnavailableException{
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));
DomainRouterVO router = profile.getVirtualMachine();

View File

@ -1133,7 +1133,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
public void completeStartCommand(UserVmVO vm) {
_itMgr.stateTransitTo(vm, VirtualMachine.Event.AgentReportRunning, vm.getHostId());
_networkGroupMgr.handleVmStateTransition(vm, State.Running);
_ovsNetworkMgr.handleVmStateTransition(vm, State.Running);
}
@Override
@ -1167,6 +1167,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
txn.commit();
_networkGroupMgr.handleVmStateTransition(vm, State.Stopped);
_ovsNetworkMgr.handleVmStateTransition(vm, State.Stopped);
} catch (Throwable th) {
s_logger.error("Error during stop: ", th);
throw new CloudRuntimeException("Error during stop: ", th);
@ -2343,7 +2344,10 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
try {
vm = _itMgr.start(vm, null, caller, owner, cmd.getHypervisor());
} finally {
} catch (Exception e) {
e.printStackTrace();
}
finally {
updateVmStateForFailedVmCreation(vm.getId());
}
vm.setPassword(password);
@ -2397,7 +2401,8 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
}
_vmDao.update(userVm.getId(), userVm);
_ovsNetworkMgr.CheckAndCreateTunnel(cmds, profile, dest);
_ovsNetworkMgr.UserVmCheckAndCreateTunnel(cmds, profile, dest);
_ovsNetworkMgr.applyDefaultFlowToUserVm(cmds, profile, dest);
return true;
}

View File

@ -1328,6 +1328,7 @@ CREATE TABLE `cloud`.`ovs_host_vlan_alloc`(
`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',
`ref` int unsigned NOT NULL DEFAULT 0 COMMENT 'reference count',
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
@ -1338,4 +1339,23 @@ CREATE TABLE `cloud`.`ovs_vlan_mapping_dirty`(
PRIMARY KEY(`id`)
) 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;