Open vSwitch tunnel manager

Applying patch with new ovs-tunnel-manager on top of cloudstack oss-master
This commit is contained in:
Salvatore Orlando 2012-03-14 12:44:45 +00:00
parent a1a615e018
commit 9f321ffeac
27 changed files with 779 additions and 460 deletions

View File

@ -48,6 +48,7 @@ public interface Network extends ControlledEntity {
public static final Service StaticNat = new Service("StaticNat", Capability.ElasticIp);
public static final Service PortForwarding = new Service("PortForwarding");
public static final Service SecurityGroup = new Service("SecurityGroup");
public static final Service Connectivity = new Service("Connectivity");
private String name;
private Capability[] caps;
@ -109,6 +110,7 @@ public interface Network extends ControlledEntity {
public static final Provider ExternalGateWay = new Provider("ExternalGateWay", true);
public static final Provider ElasticLoadBalancerVm = new Provider("ElasticLoadBalancerVm", false);
public static final Provider SecurityGroupProvider = new Provider("SecurityGroupProvider", false);
public static final Provider OvsConnectivityProvider = new Provider("OvsConnectivityProvider", false);
public static final Provider None = new Provider("None", false);
private String name;

View File

@ -18,7 +18,7 @@ import com.cloud.agent.api.Command;
public class OvsCreateTunnelAnswer extends Answer {
Long from;
Long to;
long account;
long networkId;
String inPortName;
//for debug info
@ -32,7 +32,7 @@ public class OvsCreateTunnelAnswer extends Answer {
OvsCreateTunnelCommand c = (OvsCreateTunnelCommand)cmd;
from = c.getFrom();
to = c.getTo();
account = c.getAccount();
networkId = c.getNetworkId();
inPortName = "[]";
fromIp = c.getFromIp();
toIp = c.getRemoteIp();
@ -54,8 +54,8 @@ public class OvsCreateTunnelAnswer extends Answer {
return to;
}
public long getAccount() {
return account;
public long getNetworkId() {
return networkId;
}
public String getInPortName() {
@ -78,3 +78,4 @@ public class OvsCreateTunnelAnswer extends Answer {
return bridge;
}
}

View File

@ -19,7 +19,7 @@ public class OvsCreateTunnelCommand extends Command {
String remoteIp;
Long from;
Long to;
long account;
long networkId;
// for debug info
String fromIp;
@ -29,12 +29,12 @@ public class OvsCreateTunnelCommand extends Command {
return true;
}
public OvsCreateTunnelCommand(String remoteIp, String key, Long from, Long to, long account, String fromIp) {
public OvsCreateTunnelCommand(String remoteIp, String key, Long from, Long to, long networkId, String fromIp) {
this.remoteIp = remoteIp;
this.key = key;
this.from = from;
this.to = to;
this.account = account;
this.networkId = networkId;
this.fromIp = fromIp;
}
@ -54,8 +54,8 @@ public class OvsCreateTunnelCommand extends Command {
return to;
}
public long getAccount() {
return account;
public long getNetworkId() {
return networkId;
}
public String getFromIp() {

View File

@ -15,16 +15,16 @@ package com.cloud.network.ovs;
import com.cloud.agent.api.Command;
public class OvsDestroyTunnelCommand extends Command {
long account;
long networkId;
String inPortName;
public OvsDestroyTunnelCommand(long account, String inPortName) {
this.account = account;
public OvsDestroyTunnelCommand(long networkId, String inPortName) {
this.networkId = networkId;
this.inPortName = inPortName;
}
public long getAccount() {
return account;
public long getNetworkId() {
return networkId;
}
public String getInPortName() {

View File

@ -38,6 +38,7 @@ public interface NetworkOffering {
public final static String DefaultSharedNetworkOfferingWithSGService = "DefaultSharedNetworkOfferingWithSGService";
public final static String DefaultIsolatedNetworkOfferingWithSourceNatService = "DefaultIsolatedNetworkOfferingWithSourceNatService";
public final static String OvsIsolatedNetworkOfferingWithSourceNatService = "OvsIsolatedNetworkOfferingWithSourceNatService";
public final static String DefaultSharedNetworkOffering = "DefaultSharedNetworkOffering";
public final static String DefaultIsolatedNetworkOffering = "DefaultIsolatedNetworkOffering";
public final static String DefaultSharedEIPandELBNetworkOffering = "DefaultSharedNetscalerEIPandELBNetworkOffering";

View File

@ -177,6 +177,7 @@ import com.cloud.network.ovs.OvsCreateGreTunnelCommand;
import com.cloud.network.ovs.OvsCreateTunnelAnswer;
import com.cloud.network.ovs.OvsCreateTunnelCommand;
import com.cloud.network.ovs.OvsDeleteFlowCommand;
import com.cloud.network.ovs.OvsDestroyBridgeCommand;
import com.cloud.network.ovs.OvsDestroyTunnelCommand;
import com.cloud.network.ovs.OvsSetTagAndFlowAnswer;
import com.cloud.network.ovs.OvsSetTagAndFlowCommand;
@ -488,6 +489,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
return execute((NetworkRulesSystemVmCommand)cmd);
} else if (clazz == OvsCreateTunnelCommand.class) {
return execute((OvsCreateTunnelCommand)cmd);
} else if (clazz == OvsDestroyBridgeCommand.class) {
return execute((OvsDestroyBridgeCommand)cmd);
} else if (clazz == OvsDestroyTunnelCommand.class) {
return execute((OvsDestroyTunnelCommand)cmd);
} else if (clazz == UpdateHostPasswordCommand.class) {
@ -549,21 +552,33 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
VIF dom0vif = null;
Pair<VM, VM.Record> vm = getControlDomain(conn);
VM dom0 = vm.first();
s_logger.debug("Create a vif on dom0 for " + networkDesc);
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;
// Create a VIF unless there's not already another VIF
Set<VIF> dom0Vifs = dom0.getVIFs(conn);
for (VIF vif:dom0Vifs) {
vif.getRecord(conn);
if (vif.getNetwork(conn).getUuid(conn) == nw.getUuid(conn)) {
dom0vif = vif;
s_logger.debug("### A dom0 VIF has already been found - No need to create one");
}
}
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);
if (dom0vif == null) {
s_logger.debug("Create a vif on dom0 for " + networkDesc);
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);
}
// At this stage we surely have a VIF
dom0vif.plug(conn);
dom0vif.unplug(conn);
synchronized(_tmpDom0Vif) {
@ -599,30 +614,115 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
return null;
}
private synchronized Network createTunnelNetwork(Connection conn, long account) {
/**
* This method just creates a XenServer network following the tunnel network naming convention
*/
private synchronized Network createTunnelNetwork(Connection conn, long networkId) {
try {
String nwName = "OVSTunnel" + account;
String nwName = "OVSTunnel" + networkId;
Network nw = null;
Network.Record rec = new Network.Record();
Set<Network> networks = Network.getByNameLabel(conn, nwName);
if (networks.size() == 0) {
rec.nameDescription = "tunnel network for account " + account;
rec.nameDescription = "tunnel network id# " + networkId;
rec.nameLabel = nwName;
//Initialize the ovs-host-setup to avoid error when doing get-param in plugin
Map<String,String> otherConfig = new HashMap<String,String>();
otherConfig.put("ovs-host-setup", "");
rec.otherConfig = otherConfig;
nw = Network.create(conn, rec);
} else {
nw = networks.iterator().next();
}
enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + account);
enableXenServerNetwork(conn, nw, nwName, "tunnel network for account " + networkId);
s_logger.debug("### Xen Server network for tunnels created:" + nwName);
return nw;
} catch (Exception e) {
s_logger.warn("create tunnel network failed", e);
s_logger.warn("createTunnelNetwork failed", e);
return null;
}
}
/**
* This method creates a XenServer network and configures it for being used as a L2-in-L3 tunneled network
*/
private synchronized Network createAndConfigureTunnelNetwork(Connection conn, long networkId, long hostId) {
try {
Network nw = createTunnelNetwork(conn, networkId);
//Invoke plugin to setup the bridge which will be used by this network
String bridge = nw.getBridge(conn);
Map<String,String> nwOtherConfig = nw.getOtherConfig(conn);
String configuredHosts = nwOtherConfig.get("ovs-host-setup");
boolean configured = false;
if (configuredHosts!=null) {
String hostIdsStr[] = configuredHosts.split(",");
for (String hostIdStr:hostIdsStr) {
if (hostIdStr.equals(((Long)hostId).toString())) {
configured = true;
break;
}
}
}
if (!configured) {
String result = callHostPlugin(conn, "ovstunnel", "setup_ovs_bridge", "bridge", bridge,
"key", String.valueOf(networkId),
"xs_nw_uuid", nw.getUuid(conn),
"cs_host_id", ((Long)hostId).toString());
//Note down the fact that the ovs bridge has been setup
String[] res = result.split(":");
if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) {
//TODO: Should make this error not fatal?
throw new CloudRuntimeException("Unable to pre-configure OVS bridge " + bridge + " for network ID:" + networkId +
" - " + res);
}
}
return nw;
} catch (Exception e) {
s_logger.warn("createandConfigureTunnelNetwork failed", e);
return null;
}
}
private synchronized Network findTunnelNetwork(Connection conn, long networkId) {
try {
String nwName = "OVSTunnel" + networkId;
Network nw = null;
Set<Network> networks = Network.getByNameLabel(conn, nwName);
if (networks.size() == 0) {
String errorMessage = "Unable to find OVS bridge for network:" + networkId;
s_logger.error(errorMessage);
throw new CloudRuntimeException(errorMessage);
} else {
nw = networks.iterator().next();
}
s_logger.debug("### Xen Server network for tunnels found:" + nwName);
return nw;
} catch (Exception e) {
s_logger.warn("findTunnelNetwork failed:", e);
return null;
}
}
private synchronized void destroyTunnelNetwork(Connection conn, long networkId) {
try {
Network nw = findTunnelNetwork(conn, networkId);
String bridge = nw.getBridge(conn);
String result = callHostPlugin(conn, "ovstunnel", "destroy_ovs_bridge", "bridge", bridge);
String[] res = result.split(":");
if (res.length != 2 || !res[0].equalsIgnoreCase("SUCCESS")) {
//TODO: Should make this error not fatal?
//Can Concurrent VM shutdown/migration/reboot events can cause this method
//to be executed on a bridge which has already been removed?
throw new CloudRuntimeException("Unable to remove OVS bridge " + bridge + ":" + res);
}
return;
} catch (Exception e) {
s_logger.warn("destroyTunnelNetwork failed:", e);
return;
}
}
protected Network getNetwork(Connection conn, NicTO nic) throws XenAPIException, XmlRpcException {
String name = nic.getName();
XsLocalNetwork network = getNativeNetworkForTraffic(conn, nic.getType(), name);
@ -646,8 +746,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
_isOvs = true;
return setupvSwitchNetwork(conn);
} else {
long account = Long.parseLong(nic.getBroadcastUri().getHost());
return createTunnelNetwork(conn, account);
long networkId = Long.parseLong(nic.getBroadcastUri().getHost());
return createTunnelNetwork(conn, networkId);
}
} else if (nic.getBroadcastType() == BroadcastDomainType.Storage) {
URI broadcastUri = nic.getBroadcastUri();
@ -1111,6 +1211,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
startVM(conn, host, vm, vmName);
if (_isOvs) {
// TODO(Salvatore-orlando): First option is to do per-NIC rules here
for (NicTO nic : vmSpec.getNics()) {
if (nic.getBroadcastType() == Networks.BroadcastDomainType.Vswitch) {
HashMap<String, String> args = parseDefaultOvsRuleComamnd(nic.getBroadcastUri().toString().substring(Networks.BroadcastDomainType.Vswitch.scheme().length() + "://".length()));
@ -4701,16 +4802,28 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
return Boolean.valueOf(callHostPlugin(conn, "vmops", "can_bridge_firewall", "host_uuid", _host.uuid, "instance", _instance));
}
private Answer execute(OvsDestroyBridgeCommand cmd) {
Connection conn = getConnection();
s_logger.debug("### About to destroy OVS bridge");
destroyTunnelNetwork(conn, cmd.getNetworkId());
s_logger.debug("### Bridge destroyed");
return new Answer(cmd, true, null);
}
private Answer execute(OvsDestroyTunnelCommand cmd) {
Connection conn = getConnection();
s_logger.debug("### About to destroy tunnel network");
try {
Network nw = createTunnelNetwork(conn, cmd.getAccount());
Network nw = findTunnelNetwork(conn, cmd.getNetworkId());
if (nw == null) {
s_logger.warn("### Unable to find tunnel network");
return new Answer(cmd, false, "No network found");
}
String bridge = nw.getBridge(conn);
s_logger.debug("### About to remove tunnel named:" + cmd.getInPortName());
String result = callHostPlugin(conn, "ovstunnel", "destroy_tunnel", "bridge", bridge, "in_port", cmd.getInPortName());
s_logger.debug("### Tunnel removed");
if (result.equalsIgnoreCase("SUCCESS")) {
return new Answer(cmd, true, result);
} else {
@ -4732,15 +4845,18 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
Connection conn = getConnection();
String bridge = "unknown";
try {
Network nw = createTunnelNetwork(conn, cmd.getAccount());
s_logger.debug("### About to create tunnel network");
Network nw = createAndConfigureTunnelNetwork(conn, cmd.getNetworkId(), cmd.getFrom());
if (nw == null) {
s_logger.debug("### SOMETHING WENT WRONG DURING NETWORK SETUP");
return new OvsCreateTunnelAnswer(cmd, false, "Cannot create network", bridge);
}
bridge = nw.getBridge(conn);
s_logger.debug("### The bridge is:" + bridge);
String result = callHostPlugin(conn, "ovstunnel", "create_tunnel", "bridge", bridge, "remote_ip", cmd.getRemoteIp(), "key", cmd.getKey(), "from", cmd.getFrom().toString(), "to", cmd
.getTo().toString());
s_logger.debug("### Result from create tunnel operation:" + result);
String[] res = result.split(":");
if (res.length == 2 && res[0].equalsIgnoreCase("SUCCESS")) {
return new OvsCreateTunnelAnswer(cmd, true, result, res[1], bridge);
@ -4748,7 +4864,8 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
return new OvsCreateTunnelAnswer(cmd, false, result, bridge);
}
} catch (Exception e) {
s_logger.warn("caught execption when creating ovs tunnel", e);
s_logger.debug("### SOMETHING WENT WRONG DURING TUNNEL SETUP");
s_logger.warn("caught execption when creating ovs tunnel", e);
return new OvsCreateTunnelAnswer(cmd, false, e.getMessage(), bridge);
}
}
@ -5131,12 +5248,14 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
VDI vdi = null;
try {
SR poolSr = getStorageRepository(conn, pool);
s_logger.debug("### STORAGE CREATE - Template URL:" + cmd.getTemplateUrl());
if (cmd.getTemplateUrl() != null) {
VDI tmpltvdi = null;
tmpltvdi = getVDIbyUuid(conn, cmd.getTemplateUrl());
s_logger.debug("### STORAGE CREATE - ABOUT TO CLONE VDI:" + tmpltvdi.getUuid(conn));
vdi = tmpltvdi.createClone(conn, new HashMap<String, String>());
s_logger.debug("### STORAGE CREATE - CLoned VDI:" + vdi.getUuid(conn));
vdi.setNameLabel(conn, dskch.getName());
} else {
VDI.Record vdir = new VDI.Record();
@ -5145,7 +5264,9 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
vdir.type = Types.VdiType.USER;
vdir.virtualSize = dskch.getSize();
s_logger.debug("### STORAGE CREATE - Creating VDI with size:" + dskch.getSize());
vdi = VDI.create(conn, vdir);
s_logger.debug("### STORAGE CREATE - VDI created:" + vdi.getUuid(conn));
}
VDI.Record vdir;

View File

@ -4,4 +4,7 @@
<pydev_project>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property>
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
<path>/scripts</path>
</pydev_pathproperty>
</pydev_project>

484
scripts/vm/hypervisor/xenserver/ovstunnel Normal file → Executable file
View File

@ -3,28 +3,94 @@
#
# A plugin for executing script needed by vmops cloud
import cloudstack_pluginlib as lib
import logging
import os, sys, time
import subprocess
import XenAPIPlugin
sys.path.append("/opt/xensource/sm/")
import util
from util import CommandException
import hostvmstats
import socket
import stat
import base64
import tempfile
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"
ofctlPath = "/usr/bin/ovs-ofctl"
vSwitchDaemonName = "ovs-vswitchd"
xePath= "/opt/xensource/bin/xe"
lib.setup_logging("/var/log/ovstunnel.log")
def find_vifs_v5(xs_nw_uuid):
logging.debug("Fetching vifs on networks - for XS version 5.x")
vif_uuids_cmd = [xePath, 'network-list', 'uuid=%s' %xs_nw_uuid,
'params=VIF-uuids', '--minimal']
vif_uuids_str = lib.do_cmd(vif_uuids_cmd)
vif_uuids = vif_uuids_str.split(';')
vifs = []
for vif_uuid in vif_uuids:
vif_uuid = vif_uuid.strip()
is_attached_cmd = [xePath, 'vif-list', 'uuid=%s' %vif_uuid,
'params=currently-attached', '--minimal']
is_attached = lib.do_cmd(is_attached_cmd)
# Consider only attached VIFs
if is_attached == 'false':
continue
vm_uuid_cmd = [xePath, 'vif-list', 'uuid=%s' %vif_uuid,
'params=vm-uuid', '--minimal']
vm_uuid = lib.do_cmd(vm_uuid_cmd)
dom_id_cmd = [xePath, 'vm-list', 'uuid=%s' %vm_uuid,
'params=dom-id', '--minimal']
dom_id = lib.do_cmd(dom_id_cmd)
device_cmd = [xePath, 'vif-list', 'uuid=%s' %vif_uuid,
'params=device', '--minimal']
device = lib.do_cmd(device_cmd)
vifs.append("vif%s.%s" % (dom_id, device))
logging.debug("Vifs on network:%s" %vifs)
vif_ofports = []
for vif in vifs:
vif_ofport_cmd=[lib.VSCTL_PATH, 'get', 'interface', vif, 'ofport']
vif_ofport = lib.do_cmd(vif_ofport_cmd).strip()
if vif_ofport.endswith('\n'):
vif_ofport = vif_ofport[:-1]
vif_ofports.append(vif_ofport.strip())
return vif_ofports
def find_vifs_v6(xs_nw_uuid):
logging.debug("Fetching vifs on networks - for XS version 6.x")
cmd_vif_ofports = [lib.VSCTL_PATH, "--", "--columns=ofport",
"find", "interface",
"external_ids:xs-network-uuid=%s" % xs_nw_uuid,
"type!=gre"]
vif_ofports_str = lib.do_cmd(cmd_vif_ofports)
vif_ofports = []
for line in vif_ofports_str.split('\n'):
elements = line.split(':')
if len(elements)==2:
# ensure no trailing \n is returned
if elements[1].endswith('\n'):
elements[1] = elements[1][:-1]
vif_ofports.append(elements[1].strip())
return vif_ofports
vif_ofport_list_handlers = {
'5': find_vifs_v5,
'6': find_vifs_v6}
def block_ipv6_v5(bridge):
lib.add_flow(bridge, priority=65000, dl_type='0x86dd', actions='drop')
def block_ipv6_v6(bridge):
lib.add_flow(bridge, priority=65000, proto='ipv6', actions='drop')
block_ipv6_handlers = {
'5': block_ipv6_v5,
'6': block_ipv6_v6}
class PluginError(Exception):
"""Base Exception class for all plugin errors."""
def __init__(self, *args):
Exception.__init__(self, *args)
logFile = "/var/log/ovstunnel.log"
fLog = None
def echo(fn):
def wrapped(*v, **k):
@ -35,229 +101,201 @@ def echo(fn):
return res
return wrapped
def open_log ():
global fLog
try:
if fLog == None:
fLog = open (logFile, "a")
except IOError, e:
#print e
pass
def pr (str):
global fLog
if fLog != None:
str = "[%s]:" % _asctime (_localtime()) + str + "\n"
fLog.write (str)
def close_log ():
global fLog
if fLog != None:
fLog.close ()
def is_process_run (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 is_tool_exist (name):
if _exists (name):
return 0
return -1
def check_switch ():
global result
ret = is_process_run (vSwitchDBPidFile, vSwitchDBDaemonName);
if ret < 0:
if ret == -1: return "NO_DB_PID_FILE"
if ret == -2: return "DB_NOT_RUN"
ret = is_process_run (vSwitchPidFile, vSwitchDaemonName)
if ret < 0:
if ret == -1: return "NO_SWITCH_PID_FILE"
if ret == -2: return "SWITCH_NOT_RUN"
if is_tool_exist (vsctlPath) < 0:
return "NO_VSCTL"
if is_tool_exist (ofctlPath) < 0:
return "NO_OFCTL"
return "SUCCESS"
def do_cmd (cmds, lines=False):
cmd = ""
for i in cmds:
cmd += " "
cmd += i
pr("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:
pr("command output '%s'" % res)
return res
######################## GRE creation utils ##########################
# UUID's format is 8-4-4-4-12
def is_uuid (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
def set_flood_flow(bridge, inport):
flow = "in_port=%s idle_timeout=0 hard_timeout=0 priority=10000 actions=flood" % inport
add_flow(bridge, flow)
@echo
def create_tunnel (session, args):
def setup_ovs_bridge(session, args):
bridge = args.pop("bridge")
remoteIP = args.pop("remote_ip")
greKey = args.pop("key")
srcHost = args.pop("from")
dstHost = args.pop("to")
key = args.pop("key")
xs_nw_uuid = args.pop("xs_nw_uuid")
cs_host_id = args.pop("cs_host_id")
res = lib.check_switch()
if res != "SUCCESS":
return "FAILURE:%s" %res
res = check_switch()
logging.debug("About to manually create the bridge:%s" %bridge)
# create a bridge with the same name as the xapi network
# also associate gre key in other config attribute
res = lib.do_cmd([lib.VSCTL_PATH, "--", "--may-exist", "add-br", bridge,
"--", "set", "bridge", bridge,
"other_config:gre_key=%s" % key])
logging.debug("Bridge has been manually created:%s" %res)
# TODO: Make sure xs-network-uuid is set into external_ids
lib.do_cmd([lib.VSCTL_PATH, "set", "Bridge", bridge,
"external_ids:xs-network-uuid=%s" % xs_nw_uuid])
# Non empty result means something went wrong
if res:
result = "FAILURE:%s" %res
else:
# Verify the bridge actually exists, with the gre_key properly set
res = lib.do_cmd([lib.VSCTL_PATH, "get", "bridge",
bridge, "other_config:gre_key"])
if key in res:
result = "SUCCESS:%s" %bridge
else:
result = "FAILURE:%s" %res
# Finally note in the xenapi network object that the network has
# been configured
xs_nw_uuid = lib.do_cmd([lib.XE_PATH, "network-list",
"bridge=%s" % bridge, "--minimal"])
lib.do_cmd([lib.XE_PATH,"network-param-set", "uuid=%s" % xs_nw_uuid,
"other-config:is-ovs-tun-network=True"])
conf_hosts = lib.do_cmd([lib.XE_PATH,"network-param-get",
"uuid=%s" % xs_nw_uuid,
"param-name=other-config",
"param-key=ovs-host-setup", "--minimal"])
conf_hosts = conf_hosts + ",%s" %cs_host_id
lib.do_cmd([lib.XE_PATH,"network-param-set", "uuid=%s" % xs_nw_uuid,
"other-config:ovs-host-setup=%s" %conf_hosts])
# BLOCK IPv6 - Flow spec changes with ovs version
host_list_cmd = [lib.XE_PATH, 'host-list', '--minimal']
host_list_str = lib.do_cmd(host_list_cmd)
host_uuid = host_list_str.split(',')[0].strip()
version_cmd = [lib.XE_PATH, 'host-param-get', 'uuid=%s' % host_uuid,
'param-name=software-version',
'param-key=product_version']
version = lib.do_cmd(version_cmd)
block_ipv6_handlers[version](bridge)
lib.add_flow(bridge, priority=65000, proto='ipv6', actions='drop')
logging.debug("Setup_ovs_bridge completed with result:%s" %result)
return result
@echo
def destroy_ovs_bridge(session, args):
bridge = args.pop("bridge")
res = lib.check_switch()
# TODO: Must complete this routine
if res != "SUCCESS":
return res
name = "%s-%s-%s-%s" % (bridge, srcHost, dstHost, greKey)
wait = [vsctlPath, "--timeout=30 wait-until bridge %s -- get bridge %s name" % \
(bridge, bridge)]
res = do_cmd(wait)
if bridge not in res:
pr("WARNIING:Can't find bridge %s for creating tunnel!" % bridge)
result = "COMMAND_FAILED_NO_BRIDGE"
return result
createInterface = [vsctlPath, "create interface", "name=%s" % name, \
'type=gre options:remote_ip=%s options:key=%s' % (remoteIP, greKey)]
ifaceUUID = do_cmd (createInterface)
if is_uuid (ifaceUUID) < 0:
pr("create interface failed, %s is not UUID" % ifaceUUID)
result = "COMMAND_FAILED_CREATE_INTERFACE_FAILED"
return result
createPort = [vsctlPath, "create port", "name=%s" % name, \
"interfaces=[%s]" % ifaceUUID]
portUUID = do_cmd (createPort)
if is_uuid (portUUID) < 0:
pr("create port failed, %s is not UUID" % portUUID)
result = "COMMAND_FAILED_CREATE_PORT_FAILED"
return result
addBridge = [vsctlPath, "add bridge %s" % bridge, "ports %s" % portUUID]
do_cmd (addBridge)
wait = [vsctlPath, "--timeout=30 wait-until port %s -- get port %s name" % \
(name, name)]
res = do_cmd(wait)
if name in res:
port = get_field_of_interface(name, "ofport");
if port == "[]":
return "COMMAND_FAILED_PORT_IS_[]"
noFlood = [ofctlPath, "mod-port %s %s noflood" % (bridge, \
port)]
do_cmd(noFlood)
set_flood_flow(bridge, port)
pr("create tunnel successful(bridge=%s, remote_ip=%s, key=%s, from=%s, to=%s" % \
(bridge, remoteIP, greKey, srcHost, dstHost))
result = "SUCCESS:%s" % name
res = lib.do_cmd([lib.VSCTL_PATH, "del-br", bridge])
logging.debug("Bridge has been manually removed:%s" %res)
if res:
result = "FAILURE:%s" %res
else:
pr("create gre tunnel failed")
result = "COMMAND_FAILED_CREATE_TUNNEL_FAILED"
# Note that the bridge has been removed on xapi network object
xs_nw_uuid = lib.do_cmd([xePath, "network-list",
"bridge=%s" % bridge, "--minimal"])
lib.do_cmd([xePath,"network-param-set", "uuid=%s" % xs_nw_uuid,
"other-config:ovs-setup=False"])
result = "SUCCESS:%s" %bridge
logging.debug("Destroy_ovs_bridge completed with result:%s" %result)
return result
######################## End GRE creation utils ##########################
@echo
def create_tunnel(session, args):
bridge = args.pop("bridge")
remote_ip = args.pop("remote_ip")
gre_key = args.pop("key")
src_host = args.pop("from")
dst_host = args.pop("to")
logging.debug("Entering create_tunnel")
res = lib.check_switch()
if res != "SUCCESS":
logging.debug("Openvswitch running: NO")
return "FAILURE:%s" %res
# We need to keep the name below 14 characters
# src and target are enough - consider a fixed length hash
name = "t%s-%s-%s" % (gre_key, src_host, dst_host)
# Verify the xapi bridge to be created
# NOTE: Timeout should not be necessary anymore
wait = [lib.VSCTL_PATH, "--timeout=30", "wait-until", "bridge", bridge, "--",
"get", "bridge", bridge, "name"]
res = lib.do_cmd(wait)
if bridge not in res:
logging.debug("WARNING:Can't find bridge %s for creating " +
"tunnel!" % bridge)
return "FAILURE:NO_BRIDGE"
logging.debug("bridge %s for creating tunnel - VERIFIED" % bridge)
tunnel_setup = False
drop_flow_setup = False
try:
# Create a port and configure the tunnel interface for it
add_tunnel = [lib.VSCTL_PATH, "add-port", bridge, name, "--", "set", "interface",
name, "type=gre", "options:key=%s" % gre_key,
"options:remote_ip=%s" % remote_ip]
lib.do_cmd(add_tunnel)
tunnel_setup = True
# verify port
verify_port = [lib.VSCTL_PATH, "get", "port", name, "interfaces"]
res = lib.do_cmd(verify_port)
# Expecting python-style list as output
iface_list = []
if len(res) > 2:
iface_list = res.strip()[1:-1].split(',')
if len(iface_list) != 1:
logging.debug("WARNING: Unexpected output while verifying " +
"port %s on bridge %s" %(name, bridge))
return "FAILURE:VERIFY_PORT_FAILED"
# verify interface
iface_uuid = iface_list[0]
verify_interface_key = [lib.VSCTL_PATH, "get", "interface",
iface_uuid, "options:key"]
verify_interface_ip = [lib.VSCTL_PATH, "get", "interface",
iface_uuid, "options:remote_ip"]
key_validation = lib.do_cmd(verify_interface_key)
ip_validation = lib.do_cmd(verify_interface_ip)
if not gre_key in key_validation or not remote_ip in ip_validation:
logging.debug("WARNING: Unexpected output while verifying " +
"interface %s on bridge %s" %(name, bridge))
return "FAILURE:VERIFY_INTERFACE_FAILED"
logging.debug("Tunnel interface validated:%s" %verify_interface_ip)
cmd_tun_ofport = [lib.VSCTL_PATH, "get", "interface",
iface_uuid, "ofport"]
tun_ofport = lib.do_cmd(cmd_tun_ofport)
# Ensure no trailing LF
if tun_ofport.endswith('\n'):
tun_ofport = tun_ofport[:-1]
# add flow entryies for dropping broadcast coming in from gre tunnel
lib.add_flow(bridge, priority=1000, in_port=tun_ofport,
dl_dst='ff:ff:ff:ff:ff:ff', actions='drop')
lib.add_flow(bridge, priority=1000, in_port=tun_ofport,
nw_dst='224.0.0.0/24', actions='drop')
drop_flow_setup = True
logging.debug("Broadcast drop rules added")
return "SUCCESS:%s" % name
except:
logging.debug("An unexpected error occured. Rolling back")
if tunnel_setup:
logging.debug("Deleting GRE interface")
# Destroy GRE port and interface
lib.del_port(bridge, name)
if drop_flow_setup:
# Delete flows
logging.debug("Deleting flow entries from GRE interface")
lib.del_flows(bridge, in_port=tun_ofport)
raise
def del_all_flows(bridge):
delFlow = [ofctlPath, "del-flows %s" % bridge]
do_cmd(delFlow)
normalFlow = "priority=0 idle_timeout=0 hard_timeout=0 actions=normal"
add_flow(bridge, normalFlow)
def del_flows(bridge, ofport):
delFlow = [ofctlPath, 'del-flows %s "in_port=%s"' % (bridge, ofport)]
do_cmd(delFlow)
def del_port(bridge, port):
delPort = [vsctlPath, "del-port %s %s" % (bridge, port)]
do_cmd(delPort)
@echo
def destroy_tunnel(session, args):
bridge = args.pop("bridge")
inPort = args.pop("in_port")
# delete all gre ports on bridge
if inPort == "[]":
listPorts = [vsctlPath, "list-ports %s" % bridge]
res = do_cmd(listPorts, True)
for p in res:
if bridge in p:
del_port(bridge, p)
del_all_flows(bridge)
else:
ofport = get_field_of_interface(inPort, "ofport")
del_flows(bridge, ofport)
del_port(bridge, inPort)
iface_name = args.pop("in_port")
logging.debug("Destroying tunnel at port %s for bridge %s"
% (iface_name, bridge))
ofport = get_field_of_interface(iface_name, "ofport")
lib.del_flows(bridge, in_port=ofport)
lib.del_port(bridge, iface_name)
return "SUCCESS"
def get_field_of_interface(nameOruuid, field):
listIface = [vsctlPath, "list interface", nameOruuid]
res = do_cmd(listIface, True)
for i in res:
if field in i:
(x, r) = i.split(":")
return r.lstrip().rstrip()
return None
def add_flow(bridge, flow):
param = bridge + ' "%s"' % flow
addflow = ["ovs-ofctl add-flow", param]
do_cmd (addflow)
def get_field_of_interface(iface_name, field):
get_iface_cmd = [lib.VSCTL_PATH, "get","interface", iface_name, field]
res = lib.do_cmd(get_iface_cmd)
return res
if __name__ == "__main__":
open_log()
XenAPIPlugin.dispatch({"create_tunnel":create_tunnel, "destroy_tunnel":destroy_tunnel})
close_log()
XenAPIPlugin.dispatch({"create_tunnel":create_tunnel,
"destroy_tunnel":destroy_tunnel,
"setup_ovs_bridge": setup_ovs_bridge,
"destroy_ovs_bridge": destroy_ovs_bridge})

View File

@ -441,7 +441,7 @@ def can_bridge_firewall(session, args):
os.makedirs('/var/run/cloud')
if not os.path.exists('/var/cache/cloud'):
os.makedirs('/var/cache/cloud')
get_ipset_keyword()
#get_ipset_keyword()
cleanup_rules_for_dead_vms(session)
cleanup_rules(session, args)

View File

@ -11,6 +11,10 @@
# If [source path] does not start with '/' or '~', then it is relative path to the location of the patch file.
NFSSR.py=/opt/xensource/sm
vmops=..,0755,/etc/xapi.d/plugins
xen-ovs-vif-flows.rules=..,0644,/etc/udev/rules.d
ovs-vif-flows.py=.,0755,/etc/xapi.d/plugins
cloudstack_plugins.conf=..,0644,/etc/xensource
cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins
ovsgre=..,0755,/etc/xapi.d/plugins
ovstunnel=..,0755,/etc/xapi.d/plugins
vmopsSnapshot=..,0755,/etc/xapi.d/plugins

View File

@ -11,6 +11,10 @@
# If [source path] does not start with '/' or '~', then it is relative path to the location of the patch file.
NFSSR.py=/opt/xensource/sm
vmops=..,0755,/etc/xapi.d/plugins
xen-ovs-vif-flows.rules=..,0644,/etc/udev/rules.d
ovs-vif-flows.py=.,0755,/etc/xapi.d/plugins
cloudstack_plugins.conf=..,0644,/etc/xensource
cloudstack_pluginlib.py=..,0755,/etc/xapi.d/plugins
ovsgre=..,0755,/etc/xapi.d/plugins
ovstunnel=..,0755,/etc/xapi.d/plugins
vmopsSnapshot=..,0755,/etc/xapi.d/plugins

View File

@ -106,7 +106,7 @@ import com.cloud.network.lb.dao.ElasticLbVmMapDaoImpl;
import com.cloud.network.ovs.OvsNetworkManagerImpl;
import com.cloud.network.ovs.OvsTunnelManagerImpl;
import com.cloud.network.ovs.dao.GreTunnelDaoImpl;
import com.cloud.network.ovs.dao.OvsTunnelAccountDaoImpl;
import com.cloud.network.ovs.dao.OvsTunnelNetworkDaoImpl;
import com.cloud.network.ovs.dao.OvsTunnelDaoImpl;
import com.cloud.network.ovs.dao.OvsWorkDaoImpl;
import com.cloud.network.ovs.dao.VlanMappingDaoImpl;
@ -300,7 +300,7 @@ public class DefaultComponentLibrary extends ComponentLibraryBase implements Com
addDao("VmFlowLogDao", VmFlowLogDaoImpl.class);
addDao("GreTunnelDao", GreTunnelDaoImpl.class);
addDao("OvsTunnelDao", OvsTunnelDaoImpl.class);
addDao("OvsTunnelAccountDao", OvsTunnelAccountDaoImpl.class);
addDao("OvsTunnelAccountDao", OvsTunnelNetworkDaoImpl.class);
addDao("StoragePoolWorkDao", StoragePoolWorkDaoImpl.class);
addDao("HostTagsDao", HostTagsDaoImpl.class);
addDao("NetworkDomainDao", NetworkDomainDaoImpl.class);

View File

@ -127,7 +127,8 @@ public interface NetworkManager extends NetworkService {
void prepare(VirtualMachineProfile<? extends VMInstanceVO> profile, DeployDestination dest, ReservationContext context) throws InsufficientCapacityException, ConcurrentOperationException,
ResourceUnavailableException;
void release(VirtualMachineProfile<? extends VMInstanceVO> vmProfile, boolean forced);
void release(VirtualMachineProfile<? extends VMInstanceVO> vmProfile, boolean forced) throws
ConcurrentOperationException, ResourceUnavailableException;
void cleanupNics(VirtualMachineProfile<? extends VMInstanceVO> vm);
@ -204,6 +205,8 @@ public interface NetworkManager extends NetworkService {
String getIpOfNetworkElementInVirtualNetwork(long accountId, long dataCenterId);
List<NetworkVO> listNetworksForAccount(long accountId, long zoneId, Network.GuestType type);
List<NetworkVO> listAllNetworksInAllZonesByType(Network.GuestType type);
IPAddressVO markIpAsUnavailable(long addrId);

View File

@ -1946,7 +1946,8 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
}
@Override
public void release(VirtualMachineProfile<? extends VMInstanceVO> vmProfile, boolean forced) {
public void release(VirtualMachineProfile<? extends VMInstanceVO> vmProfile, boolean forced) throws
ConcurrentOperationException, ResourceUnavailableException {
List<NicVO> nics = _nicDao.listByVmId(vmProfile.getId());
for (NicVO nic : nics) {
NetworkVO network = _networksDao.findById(nic.getNetworkId());
@ -1966,6 +1967,16 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
_nicDao.update(nic.getId(), nic);
}
}
// Perform release on network elements
for (NetworkElement element : _networkElements) {
if (s_logger.isDebugEnabled()) {
s_logger.debug("Asking " + element.getName() + " to release " + nic);
}
//NOTE: Context appear to never be used in release method
//implementations. Consider removing it from interface Element
element.release(network, profile, vmProfile, null);
}
} else {
nic.setState(Nic.State.Allocated);
updateNic(nic, network.getId(), -1);
@ -3926,6 +3937,17 @@ public class NetworkManagerImpl implements NetworkManager, NetworkService, Manag
return accountNetworks;
}
@Override
public List<NetworkVO> listAllNetworksInAllZonesByType(Network.GuestType type) {
List<NetworkVO> networks = new ArrayList<NetworkVO>();
for (NetworkVO network: _networksDao.listAll()) {
if (!isNetworkSystem(network)) {
networks.add(network);
}
}
return networks;
}
@DB
@Override
public IPAddressVO markIpAsUnavailable(long addrId) {

View File

@ -66,7 +66,8 @@ public class OvsElement extends AdapterBase implements NetworkElement {
DeployDestination dest, ReservationContext context)
throws ConcurrentOperationException, ResourceUnavailableException,
InsufficientCapacityException {
return true;
//Consider actually implementing the network here
return true;
}
@Override
@ -83,12 +84,16 @@ public class OvsElement extends AdapterBase implements NetworkElement {
return true;
}
//NOTE (Salvatore Orlando):
//The code for ovs Vlan Manager has not been touched. Only the OVS tunnel
//manager has been restored. Ideally, the code for OVS Vlan Manager should go.
_ovsVlanMgr.VmCheckAndCreateTunnel(vm, dest);
String command = _ovsVlanMgr.applyDefaultFlow(vm.getVirtualMachine(), dest);
if (command != null) {
nic.setBroadcastUri(BroadcastDomainType.Vswitch.toUri(command));
}
_ovsTunnelMgr.VmCheckAndCreateTunnel(vm, dest);
_ovsTunnelMgr.VmCheckAndCreateTunnel(vm, network, dest);
//_ovsTunnelMgr.applyDefaultFlow(vm.getVirtualMachine(), dest);
return true;
}
@ -106,7 +111,7 @@ public class OvsElement extends AdapterBase implements NetworkElement {
return true;
}
_ovsTunnelMgr.CheckAndDestroyTunnel(vm.getVirtualMachine());
_ovsTunnelMgr.CheckAndDestroyTunnel(vm.getVirtualMachine(), network);
return true;
}
@ -118,7 +123,7 @@ public class OvsElement extends AdapterBase implements NetworkElement {
@Override
public boolean isReady(PhysicalNetworkServiceProvider provider) {
return true;
return true;
}
@Override

View File

@ -64,14 +64,11 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru {
@Inject
DataCenterDao _zoneDao;
@Inject
ConfigurationDao _configDao;
@Inject
PortForwardingRulesDao _pfRulesDao;
@Inject
OvsNetworkManager _ovsNetworkMgr;
@Inject
OvsTunnelManager _tunnelMgr;
@Inject PhysicalNetworkDao _physicalNetworkDao;
@Override
public Network design(NetworkOffering offering, DeploymentPlan plan, Network userSpecified, Account owner) {
@ -167,29 +164,6 @@ public class ExternalGuestNetworkGuru extends GuestNetworkGuru {
return implemented;
}
public int getVlanOffset(long physicalNetworkId, int vlanTag) {
PhysicalNetworkVO pNetwork = _physicalNetworkDao.findById(physicalNetworkId);
if (pNetwork == null) {
throw new CloudRuntimeException("Could not find the physical Network " + physicalNetworkId + ".");
}
if (pNetwork.getVnet() == null) {
throw new CloudRuntimeException("Could not find vlan range for physical Network " + physicalNetworkId + ".");
}
String vlanRange[] = pNetwork.getVnet().split("-");
int lowestVlanTag = Integer.valueOf(vlanRange[0]);
return vlanTag - lowestVlanTag;
}
public int getGloballyConfiguredCidrSize() {
try {
String globalVlanBits = _configDao.getValue(Config.GuestVlanBits.key());
return 8 + Integer.parseInt(globalVlanBits);
} catch (Exception e) {
throw new CloudRuntimeException("Failed to read the globally configured VLAN bits size.");
}
}
@Override
public NicProfile allocate(Network config, NicProfile nic, VirtualMachineProfile<? extends VirtualMachine> vm) throws InsufficientVirtualNetworkCapcityException,
InsufficientAddressCapacityException {

View File

@ -21,6 +21,8 @@ import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.configuration.Config;
import com.cloud.configuration.dao.ConfigurationDao;
import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenter.NetworkType;
import com.cloud.dc.dao.DataCenterDao;
@ -40,12 +42,14 @@ import com.cloud.network.Network.State;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkProfile;
import com.cloud.network.NetworkVO;
import com.cloud.network.PhysicalNetworkVO;
import com.cloud.network.Networks.AddressFormat;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Networks.Mode;
import com.cloud.network.Networks.TrafficType;
import com.cloud.network.dao.IPAddressDao;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.offering.NetworkOffering;
import com.cloud.user.Account;
import com.cloud.user.UserContext;
@ -75,9 +79,13 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru {
@Inject
protected NicDao _nicDao;
@Inject
ConfigurationDao _configDao;
@Inject
protected NetworkDao _networkDao;
@Inject
IPAddressDao _ipAddressDao;
@Inject
protected PhysicalNetworkDao _physicalNetworkDao;
Random _rand = new Random(System.currentTimeMillis());
private static final TrafficType[] _trafficTypes = {TrafficType.Guest};
@ -267,6 +275,43 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru {
return new Ip4Address(ip);
}
public int getVlanOffset(long physicalNetworkId, int vlanTag) {
PhysicalNetworkVO pNetwork = _physicalNetworkDao.findById(physicalNetworkId);
if (pNetwork == null) {
throw new CloudRuntimeException("Could not find the physical Network " + physicalNetworkId + ".");
}
if (pNetwork.getVnet() == null) {
throw new CloudRuntimeException("Could not find vlan range for physical Network " + physicalNetworkId + ".");
}
String vlanRange[] = pNetwork.getVnet().split("-");
int lowestVlanTag = Integer.valueOf(vlanRange[0]);
return vlanTag - lowestVlanTag;
}
public int getGloballyConfiguredCidrSize() {
try {
String globalVlanBits = _configDao.getValue(Config.GuestVlanBits.key());
return 8 + Integer.parseInt(globalVlanBits);
} catch (Exception e) {
throw new CloudRuntimeException("Failed to read the globally configured VLAN bits size.");
}
}
protected void allocateVnet(Network network, NetworkVO implemented, long dcId,
long physicalNetworkId, String reservationId) throws InsufficientVirtualNetworkCapcityException {
if (network.getBroadcastUri() == null) {
String vnet = _dcDao.allocateVnet(dcId, physicalNetworkId, network.getAccountId(), reservationId);
if (vnet == null) {
throw new InsufficientVirtualNetworkCapcityException("Unable to allocate vnet as a part of network " + network + " implement ", DataCenter.class, dcId);
}
implemented.setBroadcastUri(BroadcastDomainType.Vlan.toUri(vnet));
EventUtils.saveEvent(UserContext.current().getCallerUserId(), network.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ZONE_VLAN_ASSIGN, "Assigned Zone Vlan: "+vnet+ " Network Id: "+network.getId(), 0);
} else {
implemented.setBroadcastUri(network.getBroadcastUri());
}
}
@Override
public Network implement(Network network, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException {
assert (network.getState() == State.Implementing) : "Why are we implementing " + network;
@ -279,16 +324,7 @@ public class GuestNetworkGuru extends AdapterBase implements NetworkGuru {
NetworkVO implemented = new NetworkVO(network.getTrafficType(), network.getMode(), network.getBroadcastDomainType(), network.getNetworkOfferingId(), State.Allocated,
network.getDataCenterId(), physicalNetworkId);
if (network.getBroadcastUri() == null) {
String vnet = _dcDao.allocateVnet(dcId, physicalNetworkId, network.getAccountId(), context.getReservationId());
if (vnet == null) {
throw new InsufficientVirtualNetworkCapcityException("Unable to allocate vnet as a part of network " + network + " implement ", DataCenter.class, dcId);
}
implemented.setBroadcastUri(BroadcastDomainType.Vlan.toUri(vnet));
EventUtils.saveEvent(UserContext.current().getCallerUserId(), network.getAccountId(), EventVO.LEVEL_INFO, EventTypes.EVENT_ZONE_VLAN_ASSIGN, "Assigned Zone Vlan: "+vnet+ " Network Id: "+network.getId(), 0);
} else {
implemented.setBroadcastUri(network.getBroadcastUri());
}
allocateVnet(network, implemented, dcId, physicalNetworkId, context.getReservationId());
if (network.getGateway() != null) {
implemented.setGateway(network.getGateway());

View File

@ -14,8 +14,11 @@ package com.cloud.network.guru;
import javax.ejb.Local;
import org.apache.log4j.Logger;
import com.cloud.deploy.DeployDestination;
import com.cloud.deploy.DeploymentPlan;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientVirtualNetworkCapcityException;
import com.cloud.network.Network;
import com.cloud.network.NetworkManager;
@ -25,12 +28,18 @@ import com.cloud.network.ovs.OvsTunnelManager;
import com.cloud.offering.NetworkOffering;
import com.cloud.user.Account;
import com.cloud.utils.component.Inject;
import com.cloud.vm.Nic.ReservationStrategy;
import com.cloud.vm.NicProfile;
import com.cloud.vm.ReservationContext;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.network.Networks.BroadcastDomainType;
import com.cloud.network.Network.State;
@Local(value=NetworkGuru.class)
public class OvsGuestNetworkGuru extends GuestNetworkGuru {
private static final Logger s_logger = Logger.getLogger(OvsGuestNetworkGuru.class);
@Inject OvsNetworkManager _ovsNetworkMgr;
@Inject NetworkManager _externalNetworkManager;
@Inject OvsTunnelManager _ovsTunnelMgr;
@ -52,23 +61,29 @@ public class OvsGuestNetworkGuru extends GuestNetworkGuru {
return config;
}
protected void allocateVnet(Network network, NetworkVO implemented, long dcId,
long physicalNetworkId, String reservationId) throws InsufficientVirtualNetworkCapcityException {
// Overriden as an empty method to avoid Vnet allocation when OVS is the network manager
}
@Override
public Network implement(Network config, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException {
public Network implement(Network config, NetworkOffering offering, DeployDestination dest, ReservationContext context) throws InsufficientVirtualNetworkCapcityException {
assert (config.getState() == State.Implementing) : "Why are we implementing " + config;
if (!_ovsNetworkMgr.isOvsNetworkEnabled()&& !_ovsTunnelMgr.isOvsTunnelEnabled()) {
return null;
}
s_logger.debug("### Implementing network:" + config.getId() + " in OVS Guest Network Guru");
// The above call will NOT reserve a Vnet
NetworkVO implemented = (NetworkVO)super.implement(config, offering, dest, context);
String uri = null;
if (_ovsNetworkMgr.isOvsNetworkEnabled()) {
uri = "vlan";
} else if (_ovsTunnelMgr.isOvsTunnelEnabled()) {
uri = Long.toString(config.getAccountId());
uri = Long.toString(config.getId());
}
s_logger.debug("### URI value:" + uri);
implemented.setBroadcastUri(BroadcastDomainType.Vswitch.toUri(uri));
s_logger.debug("### Broadcast URI is:" + implemented.getBroadcastUri().toString());
return implemented;
}

View File

@ -29,6 +29,9 @@ import com.cloud.host.Host;
import com.cloud.host.HostVO;
import com.cloud.host.Status;
import com.cloud.host.dao.HostDao;
import com.cloud.network.Network.GuestType;
import com.cloud.network.NetworkManager;
import com.cloud.network.NetworkVO;
import com.cloud.network.ovs.dao.GreTunnelVO;
import com.cloud.network.ovs.dao.OvsTunnelDao;
import com.cloud.network.ovs.dao.OvsTunnelVO;
@ -40,12 +43,14 @@ public class OvsTunnelListener implements Listener {
HostDao _hostDao;
OvsTunnelDao _tunnelDao;
ResourceManager _resourceMgr;
NetworkManager _networkMgr;
public OvsTunnelListener(OvsTunnelDao tunnelDao, HostDao hostDao) {
this._hostDao = hostDao;
this._tunnelDao = tunnelDao;
ComponentLocator locator = ComponentLocator.getLocator("management-server");
_resourceMgr = locator.getManager(ResourceManager.class);
_networkMgr = locator.getManager(NetworkManager.class);
}
@Override
@ -74,36 +79,38 @@ public class OvsTunnelListener implements Listener {
return;
}
try {
List<HostVO> hosts = _resourceMgr.listAllHostsInAllZonesByType(Host.Type.Routing);
for (HostVO h : hosts) {
if (h.getId() == host.getId()) {
continue;
}
OvsTunnelVO t = _tunnelDao.getByFromAndTo(host.getId(), h.getId());
if (t == null) {
t = new OvsTunnelVO(host.getId(), h.getId());
try {
_tunnelDao.persist(t);
} catch (EntityExistsException e) {
s_logger.debug(String.format("Already has (from=%1$s, to=%2$s)", host.getId(), h.getId()));
}
}
t = _tunnelDao.getByFromAndTo(h.getId(), host.getId());
if (t == null) {
t = new OvsTunnelVO(h.getId(), host.getId());
try {
_tunnelDao.persist(t);
} catch (EntityExistsException e) {
s_logger.debug(String.format("Already has (from=%1$s, to=%2$s)", h.getId(), host.getId()));
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
//try {
//List<HostVO> hosts = _resourceMgr.listAllHostsInAllZonesByType(Host.Type.Routing);
// NOTE: Trying to semplfy things by removing tunnel pre-allocation
//List<NetworkVO> networks = _networkMgr.listAllNetworksInAllZonesByType(GuestType.Isolated);
//for (HostVO h : hosts) {
// if (h.getId() == host.getId()) {
// continue;
// }
//
// OvsTunnelVO t = _tunnelDao.getByFromAndTo(host.getId(), h.getId());
// if (t == null) {
// t = new OvsTunnelVO(host.getId(), h.getId());
// try {
// _tunnelDao.persist(t);
// } catch (EntityExistsException e) {
// s_logger.debug(String.format("Already has (from=%1$s, to=%2$s)", host.getId(), h.getId()));
// }
// }
//
// t = _tunnelDao.getByFromAndTo(h.getId(), host.getId());
// if (t == null) {
// t = new OvsTunnelVO(h.getId(), host.getId());
// try {
// _tunnelDao.persist(t);
// } catch (EntityExistsException e) {
// s_logger.debug(String.format("Already has (from=%1$s, to=%2$s)", h.getId(), host.getId()));
// }
// }
//}
//} catch (Exception e) {
//e.printStackTrace();
//}
}
@Override

View File

@ -12,19 +12,18 @@
// Automatically generated by addcopyright.py at 04/03/2012
package com.cloud.network.ovs;
import com.cloud.agent.manager.Commands;
import com.cloud.deploy.DeployDestination;
import com.cloud.network.Network;
import com.cloud.utils.component.Manager;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachineProfile;
public interface OvsTunnelManager extends Manager {
boolean isOvsTunnelEnabled();
public void VmCheckAndCreateTunnel(VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest);
public void VmCheckAndCreateTunnel(VirtualMachineProfile<? extends VirtualMachine> vm, Network nw, DeployDestination dest);
public void CheckAndDestroyTunnel(VirtualMachine vm);
public void CheckAndDestroyTunnel(VirtualMachine vm, Network nw);
public void applyDefaultFlow(VirtualMachine instance, DeployDestination dest);
}

View File

@ -33,8 +33,9 @@ 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.ovs.dao.OvsTunnelAccountDao;
import com.cloud.network.ovs.dao.OvsTunnelAccountVO;
import com.cloud.network.Network;
import com.cloud.network.ovs.dao.OvsTunnelNetworkDao;
import com.cloud.network.ovs.dao.OvsTunnelNetworkVO;
import com.cloud.network.ovs.dao.OvsTunnelDao;
import com.cloud.utils.Pair;
import com.cloud.utils.component.Inject;
@ -42,11 +43,14 @@ import com.cloud.utils.concurrency.NamedThreadFactory;
import com.cloud.utils.db.DB;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.vm.DomainRouterVO;
import com.cloud.vm.NicVO;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
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={OvsTunnelManager.class})
@ -57,14 +61,13 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager {
boolean _isEnabled;
ScheduledExecutorService _executorPool;
ScheduledExecutorService _cleanupExecutor;
OvsTunnelListener _listener;
@Inject ConfigurationDao _configDao;
@Inject OvsTunnelDao _tunnelDao;
@Inject NicDao _nicDao;
@Inject HostDao _hostDao;
@Inject UserVmDao _userVmDao;
@Inject DomainRouterDao _routerDao;
@Inject OvsTunnelAccountDao _tunnelAccountDao;
@Inject OvsTunnelNetworkDao _tunnelNetworkDao;
@Inject AgentManager _agentMgr;
@Override
@ -76,37 +79,32 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager {
if (_isEnabled) {
_executorPool = Executors.newScheduledThreadPool(10, new NamedThreadFactory("OVS"));
_cleanupExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("OVS-Cleanup"));
_listener = new OvsTunnelListener(_tunnelDao, _hostDao);
_agentMgr.registerForHostEvents(_listener, true, true, true);
}
return true;
}
protected int getGreKey(long from, long to, long account) {
OvsTunnelAccountVO ta = null;
int key;
protected OvsTunnelNetworkVO createTunnelRecord(long from, long to, long networkId) {
OvsTunnelNetworkVO ta = null;
try {
key = _tunnelDao.askKey(from, to);
ta = new OvsTunnelAccountVO(from, to, key, account);
OvsTunnelAccountVO lock = _tunnelAccountDao.acquireInLockTable(Long.valueOf(1));
// Use the network id as a Key
// FIXME: networkid is long, key must be integer
// This is a horrible cast, and it must be removed and replace with something better
// before committing into master
ta = new OvsTunnelNetworkVO(from, to, (int)networkId, networkId);
OvsTunnelNetworkVO lock = _tunnelNetworkDao.acquireInLockTable(Long.valueOf(1));
if (lock == null) {
s_logger.warn("Cannot lock table ovs_tunnel_account");
return -1;
return null;
}
_tunnelAccountDao.persist(ta);
_tunnelAccountDao.releaseFromLockTable(lock.getId());
_tunnelNetworkDao.persist(ta);
_tunnelNetworkDao.releaseFromLockTable(lock.getId());
} catch (EntityExistsException e) {
ta = _tunnelAccountDao.getByFromToAccount(from, to, account);
if (ta == null) {
key = -1;
} else {
key = ta.getKey();
}
s_logger.debug("A record for the tunnel from " + from + " to " + to + " already exists");
}
return key;
return ta;
}
private void handleCreateTunnelAnswer(Answer[] answers){
@ -116,12 +114,12 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager {
r.getFromIp(), r.getToIp(), r.getBridge(), r.getKey(), r.getInPortName());
Long from = r.getFrom();
Long to = r.getTo();
long account = r.getAccount();
OvsTunnelAccountVO ta = _tunnelAccountDao.getByFromToAccount(from, to, account);
long networkId = r.getNetworkId();
OvsTunnelNetworkVO ta = _tunnelNetworkDao.getByFromToNetwork(from, to, networkId);
if (ta == null) {
throw new CloudRuntimeException(String.format("Unable find tunnelAccount record(from=%1$s, to=%2$s, account=%3$s", from, to, account));
throw new CloudRuntimeException(String.format("Unable find tunnelAccount record(from=%1$s, to=%2$s, account=%3$s", from, to, networkId));
}
s_logger.debug("Result:" + r.getResult());
if (!r.getResult()) {
ta.setState("FAILED");
s_logger.warn("Create GRE tunnel failed due to " + r.getDetails() + s);
@ -130,24 +128,28 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager {
ta.setPortName(r.getInPortName());
s_logger.warn("Create GRE tunnel " + r.getDetails() + s);
}
_tunnelAccountDao.update(ta.getId(), ta);
_tunnelNetworkDao.update(ta.getId(), ta);
}
@DB
protected void CheckAndCreateTunnel(VirtualMachine instance, DeployDestination dest) {
protected void CheckAndCreateTunnel(VirtualMachine instance, Network nw, DeployDestination dest) {
if (!_isEnabled) {
return;
}
s_logger.debug("Creating tunnels with OVS tunnel manager");
if (instance.getType() != VirtualMachine.Type.User
&& instance.getType() != VirtualMachine.Type.DomainRouter) {
s_logger.debug("Will not work if you're not an instance or a virtual router");
return;
}
long hostId = dest.getHost().getId();
long accountId = instance.getAccountId();
List<UserVmVO>vms = _userVmDao.listByAccountId(accountId);
List<DomainRouterVO> routers = _routerDao.findBy(accountId, instance.getDataCenterIdToDeployIn());
// Find active (i.e.: not shut off) VMs with a NIC on the target network
List<UserVmVO> vms = _userVmDao.listByNetworkIdAndStates(nw.getId(), State.Running, State.Starting,
State.Stopping, State.Unknown, State.Migrating);
// Find routers for the network
List<DomainRouterVO> routers = _routerDao.findByNetwork(nw.getId());
List<VMInstanceVO>ins = new ArrayList<VMInstanceVO>();
if (vms != null) {
ins.addAll(vms);
@ -155,62 +157,61 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager {
if (routers.size() != 0) {
ins.addAll(routers);
}
List<Pair<Long, Integer>>toHosts = new ArrayList<Pair<Long, Integer>>();
List<Pair<Long, Integer>>fromHosts = new ArrayList<Pair<Long, Integer>>();
int key;
s_logger.debug("### Virtual Machines:" + vms.size());
s_logger.debug("### Virtual Routers:" + routers.size());
List<Long> toHostIds = new ArrayList<Long>();
List<Long> fromHostIds = new ArrayList<Long>();
for (VMInstanceVO v : ins) {
Long rh = v.getHostId();
if (rh == null || rh.longValue() == hostId) {
continue;
}
OvsTunnelAccountVO ta = _tunnelAccountDao.getByFromToAccount(hostId, rh.longValue(), accountId);
if (ta == null) {
key = getGreKey(hostId, rh.longValue(), accountId);
if (key == -1) {
s_logger.warn(String.format("Cannot get GRE key for from=%1$s to=%2$s accountId=%3$s, tunnel create failed", hostId, rh.longValue(), accountId));
continue;
}
Pair<Long, Integer> p = new Pair<Long, Integer>(rh, Integer.valueOf(key));
if (!toHosts.contains(p)) {
toHosts.add(p);
//FIXME: Still using 'TunnelAccount name' - but should actually be tunnelNetwork or something like that
OvsTunnelNetworkVO ta = _tunnelNetworkDao.getByFromToNetwork(hostId, rh.longValue(), nw.getId());
// Try and create the tunnel even if a previous attempt failed
if (ta == null || ta.getState().equals("FAILED")) {
s_logger.debug("Attempting to create tunnel from:" + hostId + " to:" + rh.longValue());
if (ta == null) {
this.createTunnelRecord(hostId, rh.longValue(), nw.getId());
}
if (!toHostIds.contains(rh)) {
toHostIds.add(rh);
}
}
ta = _tunnelAccountDao.getByFromToAccount(rh.longValue(), hostId, accountId);
if (ta == null) {
key = getGreKey(rh.longValue(), hostId, accountId);
if (key == -1) {
s_logger.warn(String.format("Cannot get GRE key for from=%1$s to=%2$s accountId=%3$s, tunnel create failed", rh.longValue(), hostId, accountId));
continue;
}
Pair<Long, Integer> p = new Pair<Long, Integer>(rh, Integer.valueOf(key));
if (!fromHosts.contains(p)) {
fromHosts.add(p);
ta = _tunnelNetworkDao.getByFromToNetwork(rh.longValue(), hostId, nw.getId());
// Try and create the tunnel even if a previous attempt failed
if (ta == null || ta.getState().equals("FAILED")) {
s_logger.debug("Attempting to create tunnel from:" + rh.longValue() + " to:" + hostId);
if (ta == null) {
this.createTunnelRecord(rh.longValue(), hostId, nw.getId());
}
if (!fromHostIds.contains(rh)) {
fromHostIds.add(rh);
}
}
}
try {
String myIp = dest.getHost().getPrivateIpAddress();
for (Pair<Long, Integer> i : toHosts) {
HostVO rHost = _hostDao.findById(i.first());
for (Long i : toHostIds) {
HostVO rHost = _hostDao.findById(i);
Commands cmds = new Commands(
new OvsCreateTunnelCommand(rHost.getPrivateIpAddress(), i.second().toString(), Long.valueOf(hostId), i.first(), accountId, myIp));
s_logger.debug("Ask host " + hostId + " to create gre tunnel to " + i.first());
new OvsCreateTunnelCommand(rHost.getPrivateIpAddress(), String.valueOf(nw.getId()),
Long.valueOf(hostId), i, nw.getId(), myIp));
s_logger.debug("Ask host " + hostId + " to create gre tunnel to " + i);
Answer[] answers = _agentMgr.send(hostId, cmds);
handleCreateTunnelAnswer(answers);
}
for (Pair<Long, Integer> i : fromHosts) {
HostVO rHost = _hostDao.findById(i.first());
for (Long i : fromHostIds) {
HostVO rHost = _hostDao.findById(i);
Commands cmd2s = new Commands(
new OvsCreateTunnelCommand(myIp, i.second().toString(), i.first(), Long.valueOf(hostId), accountId, rHost.getPrivateIpAddress()));
s_logger.debug("Ask host " + i.first() + " to create gre tunnel to " + hostId);
Answer[] answers = _agentMgr.send(i.first(), cmd2s);
new OvsCreateTunnelCommand(myIp, String.valueOf(nw.getId()),
i, Long.valueOf(hostId), nw.getId(), rHost.getPrivateIpAddress()));
s_logger.debug("Ask host " + i + " to create gre tunnel to " + hostId);
Answer[] answers = _agentMgr.send(i, cmd2s);
handleCreateTunnelAnswer(answers);
}
} catch (Exception e) {
@ -239,67 +240,91 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager {
}
@Override
public void VmCheckAndCreateTunnel(VirtualMachineProfile<? extends VirtualMachine> vm, DeployDestination dest) {
CheckAndCreateTunnel(vm.getVirtualMachine(), dest);
public void VmCheckAndCreateTunnel(VirtualMachineProfile<? extends VirtualMachine> vm, Network nw, DeployDestination dest) {
CheckAndCreateTunnel(vm.getVirtualMachine(), nw, dest);
}
private void handleDestroyTunnelAnswer(Answer ans, long from, long to, long account) {
String toStr = (to == 0 ? "all peers" : Long.toString(to));
private void handleDestroyTunnelAnswer(Answer ans, long from, long to, long network_id) {
if (ans.getResult()) {
OvsTunnelAccountVO lock = _tunnelAccountDao.acquireInLockTable(Long.valueOf(1));
OvsTunnelNetworkVO lock = _tunnelNetworkDao.acquireInLockTable(Long.valueOf(1));
if (lock == null) {
s_logger.warn(String.format("failed to lock ovs_tunnel_account, remove record of tunnel(from=%1$s, to=%2$s account=%3$s) failed", from, to, account));
s_logger.warn(String.format("failed to lock ovs_tunnel_account, remove record of " +
"tunnel(from=%1$s, to=%2$s account=%3$s) failed",
from, to, network_id));
return;
}
if (to == 0) {
_tunnelAccountDao.removeByFromAccount(from, account);
} else {
_tunnelAccountDao.removeByFromToAccount(from, to, account);
}
_tunnelAccountDao.releaseFromLockTable(lock.getId());
_tunnelNetworkDao.removeByFromToNetwork(from, to, network_id);
_tunnelNetworkDao.releaseFromLockTable(lock.getId());
s_logger.debug(String.format("Destroy tunnel(account:%1$s, from:%2$s, to:%3$s) successful", account, from, toStr));
s_logger.debug(String.format("Destroy tunnel(account:%1$s, from:%2$s, to:%3$s) successful",
network_id, from, to));
} else {
s_logger.debug(String.format("Destroy tunnel(account:%1$s, from:%2$s, to:%3$s) failed", account, from, toStr));
s_logger.debug(String.format("Destroy tunnel(account:%1$s, from:%2$s, to:%3$s) failed",
network_id, from, to));
}
}
private void handleDestroyBridgeAnswer(Answer ans, long host_id, long network_id) {
if (ans.getResult()) {
OvsTunnelNetworkVO lock = _tunnelNetworkDao.acquireInLockTable(Long.valueOf(1));
if (lock == null) {
s_logger.warn("failed to lock ovs_tunnel_network, remove record");
return;
}
_tunnelNetworkDao.removeByFromNetwork(host_id, network_id);
_tunnelNetworkDao.releaseFromLockTable(lock.getId());
s_logger.debug(String.format("Destroy bridge for network %1$s successful", network_id));
} else {
s_logger.debug(String.format("Destroy bridge for network %1$s failed", network_id));
}
}
@Override
public void CheckAndDestroyTunnel(VirtualMachine vm) {
if (!_isEnabled) {
public void CheckAndDestroyTunnel(VirtualMachine vm, Network nw) {
s_logger.debug("### DESTROYING YOUR TUNNELS!");
if (!_isEnabled) {
return;
}
List<UserVmVO> userVms = _userVmDao.listByAccountIdAndHostId(vm.getAccountId(), vm.getHostId());
s_logger.debug("### User Vms:" + userVms.size());
if (vm.getType() == VirtualMachine.Type.User) {
if (userVms.size() > 1) {
return;
}
List<DomainRouterVO> routers = _routerDao.findBy(vm.getAccountId(), vm.getDataCenterIdToDeployIn());
List<DomainRouterVO> routers = _routerDao.findByNetwork(nw.getId());
for (DomainRouterVO router : routers) {
if (router.getHostId() == vm.getHostId()) {
return;
s_logger.debug("### Not destroying because on same host as router");
return;
}
}
} else if (vm.getType() == VirtualMachine.Type.DomainRouter && userVms.size() != 0) {
return;
}
s_logger.debug("### I WILL DESTROYYY");
try {
/* Now we are last one on host, destroy all tunnels of my account */
Command cmd = new OvsDestroyTunnelCommand(vm.getAccountId(), "[]");
/* Now we are last one on host, destroy the bridge with all
* the tunnels for this network */
Command cmd = new OvsDestroyBridgeCommand(nw.getId());
s_logger.debug("### Destroying bridge for network " + nw.getId() + " on host:" + vm.getHostId());
Answer ans = _agentMgr.send(vm.getHostId(), cmd);
handleDestroyTunnelAnswer(ans, vm.getHostId(), 0, vm.getAccountId());
handleDestroyBridgeAnswer(ans, vm.getHostId(), nw.getId());
/* Then ask hosts have peer tunnel with me to destroy them */
List<OvsTunnelAccountVO> peers = _tunnelAccountDao.listByToAccount(vm.getHostId(), vm.getAccountId());
for (OvsTunnelAccountVO p : peers) {
cmd = new OvsDestroyTunnelCommand(p.getAccount(), p.getPortName());
List<OvsTunnelNetworkVO> peers = _tunnelNetworkDao.listByToNetwork(vm.getHostId(), nw.getId());
for (OvsTunnelNetworkVO p : peers) {
cmd = new OvsDestroyTunnelCommand(p.getNetworkId(), p.getPortName());
s_logger.debug("### Destroying tunnel to " + vm.getHostId() +
" from " + p.getFrom());
ans = _agentMgr.send(p.getFrom(), cmd);
handleDestroyTunnelAnswer(ans, p.getFrom(), p.getTo(), p.getAccount());
handleDestroyTunnelAnswer(ans, p.getFrom(), p.getTo(), p.getNetworkId());
}
} catch (Exception e) {
s_logger.warn(String.format("Destroy tunnel(account:%1$s, hostId:%2$s) failed", vm.getAccountId(), vm.getHostId()), e);
@ -307,4 +332,21 @@ public class OvsTunnelManagerImpl implements OvsTunnelManager {
}
@Override
public void applyDefaultFlow(VirtualMachine instance,
DeployDestination dest) {
if (!_isEnabled) {
return;
}
VirtualMachine.Type vmType = instance.getType();
if (vmType != VirtualMachine.Type.User
&& vmType != VirtualMachine.Type.DomainRouter) {
return;
}
s_logger.debug("### Applying rules for allowing broadcast traffic");
}
}

View File

@ -22,6 +22,7 @@ import com.cloud.network.NetworkServiceMapVO;
import com.cloud.network.Network.Service;
import com.cloud.network.Network.Provider;
import com.cloud.offerings.NetworkOfferingServiceMapVO;
import com.cloud.offerings.NetworkOfferingVO;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.GenericDaoBase;
import com.cloud.utils.db.GenericSearchBuilder;
@ -31,7 +32,8 @@ import com.cloud.utils.db.SearchCriteria.Func;
@Local(value=NetworkOfferingServiceMapDao.class) @DB(txn=false)
public class NetworkOfferingServiceMapDaoImpl extends GenericDaoBase<NetworkOfferingServiceMapVO, Long> implements NetworkOfferingServiceMapDao {
final SearchBuilder<NetworkOfferingServiceMapVO> AllFieldsSearch;
final SearchBuilder<NetworkOfferingServiceMapVO> AllFieldsSearch;
final SearchBuilder<NetworkOfferingServiceMapVO> MultipleServicesSearch;
final GenericSearchBuilder<NetworkOfferingServiceMapVO, String> ProvidersSearch;
final GenericSearchBuilder<NetworkOfferingServiceMapVO, String> ServicesSearch;
@ -133,7 +135,18 @@ public class NetworkOfferingServiceMapDaoImpl extends GenericDaoBase<NetworkOffe
public List<String> listServicesForNetworkOffering(long networkOfferingId) {
SearchCriteria<String> sc = ServicesSearch.create();;
sc.setParameters("networkOfferingId", networkOfferingId);
return customSearch(sc, null);
}
@Override
public NetworkOfferingServiceMapVO persist(
NetworkOfferingServiceMapVO entity) {
SearchCriteria<NetworkOfferingServiceMapVO> sc = AllFieldsSearch.create();
sc.setParameters("networkOfferingId", entity.getNetworkOfferingId());
sc.setParameters("service", entity.getService());
sc.setParameters("provider", entity.getProvider());
NetworkOfferingServiceMapVO mappingInDb = findOneBy(sc);
return mappingInDb!=null? mappingInDb : super.persist(entity);
}
}

View File

@ -94,6 +94,7 @@ import com.cloud.utils.PropertiesUtil;
import com.cloud.utils.component.ComponentLocator;
import com.cloud.utils.crypt.DBEncryptionUtil;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.db.Transaction;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.net.NetUtils;
@ -892,6 +893,9 @@ public class ConfigurationServerImpl implements ConfigurationServer {
defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.PortForwarding, Provider.VirtualRouter);
defaultIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.Vpn, Provider.VirtualRouter);
Map<Network.Service, Network.Provider> ovsIsolatedSourceNatEnabledNetworkOfferingProviders =
new HashMap<Network.Service, Network.Provider>(defaultIsolatedSourceNatEnabledNetworkOfferingProviders);
ovsIsolatedSourceNatEnabledNetworkOfferingProviders.put(Service.Connectivity, Provider.OvsConnectivityProvider);
Map<Network.Service, Network.Provider> netscalerServiceProviders = new HashMap<Network.Service, Network.Provider>();
netscalerServiceProviders.put(Service.Dhcp, Provider.VirtualRouter);
netscalerServiceProviders.put(Service.Dns, Provider.VirtualRouter);
@ -906,18 +910,18 @@ public class ConfigurationServerImpl implements ConfigurationServer {
txn.start();
// Offering #1
NetworkOfferingVO deafultSharedSGNetworkOffering = new NetworkOfferingVO(
NetworkOfferingVO defaultSharedSGNetworkOffering = new NetworkOfferingVO(
NetworkOffering.DefaultSharedNetworkOfferingWithSGService,
"Offering for Shared Security group enabled networks",
TrafficType.Guest,
false, true, null, null, true, Availability.Optional,
null, Network.GuestType.Shared, true, true);
deafultSharedSGNetworkOffering.setState(NetworkOffering.State.Enabled);
deafultSharedSGNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(deafultSharedSGNetworkOffering);
defaultSharedSGNetworkOffering.setState(NetworkOffering.State.Enabled);
defaultSharedSGNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(defaultSharedSGNetworkOffering);
for (Service service : defaultSharedSGNetworkOfferingProviders.keySet()) {
NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(deafultSharedSGNetworkOffering.getId(), service, defaultSharedSGNetworkOfferingProviders.get(service));
NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(defaultSharedSGNetworkOffering.getId(), service, defaultSharedSGNetworkOfferingProviders.get(service));
_ntwkOfferingServiceMapDao.persist(offService);
s_logger.trace("Added service for the network offering: " + offService);
}
@ -989,7 +993,25 @@ public class ConfigurationServerImpl implements ConfigurationServer {
_ntwkOfferingServiceMapDao.persist(offService);
s_logger.trace("Added service for the network offering: " + offService);
}
// Offering #6 - OVS
s_logger.debug("Adding network offering for OVS networks");
NetworkOfferingVO ovsIsolatedSourceNatEnabledNetworkOffering = new NetworkOfferingVO(
NetworkOffering.OvsIsolatedNetworkOfferingWithSourceNatService,
"Offering for OVS-based Isolated networks with Source Nat service enabled",
TrafficType.Guest,
false, false, null, null, true, Availability.Optional,
null, Network.GuestType.Isolated, true, false);
ovsIsolatedSourceNatEnabledNetworkOffering.setState(NetworkOffering.State.Enabled);
ovsIsolatedSourceNatEnabledNetworkOffering = _networkOfferingDao.persistDefaultNetworkOffering(ovsIsolatedSourceNatEnabledNetworkOffering);
for (Service service : ovsIsolatedSourceNatEnabledNetworkOfferingProviders.keySet()) {
NetworkOfferingServiceMapVO offService = new NetworkOfferingServiceMapVO(ovsIsolatedSourceNatEnabledNetworkOffering.getId(), service, ovsIsolatedSourceNatEnabledNetworkOfferingProviders.get(service));
_ntwkOfferingServiceMapDao.persist(offService);
s_logger.debug("Added service for the OVS network offering: " + offService);
}
txn.commit();
}

View File

@ -3137,7 +3137,7 @@ public class UserVmManagerImpl implements UserVmManager, UserVmService, Manager
if (storageId != null) {
sc.setJoinParameters("volumeSearch", "poolId", storageId);
}
s_logger.debug("THE WHERE CLAUSE IS:" + sc.getWhereClause());
return _vmDao.search(sc, searchFilter);
}

View File

@ -385,7 +385,7 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
}
VirtualMachineProfile<T> profile = new VirtualMachineProfileImpl<T>(vm);
s_logger.debug("Cleaning up NICS");
_networkMgr.cleanupNics(profile);
// Clean up volumes based on the vm's instance id
_storageMgr.cleanupVolumes(vm.getId());
@ -949,7 +949,13 @@ public class VirtualMachineManagerImpl implements VirtualMachineManager, Listene
}
}
_networkMgr.release(profile, force);
try {
_networkMgr.release(profile, force);
s_logger.debug("Successfully released network resources for the vm " + vm);
} catch (Exception e) {
s_logger.warn("Unable to release some network resources.", e);
}
_storageMgr.release(profile);
s_logger.debug("Successfully cleanued up resources for the vm " + vm + " in " + state + " state");
return true;

View File

@ -134,6 +134,7 @@ public class DomainRouterDaoImpl extends GenericDaoBase<DomainRouterVO, Long> im
return listBy(sc);
}
@Override
public List<DomainRouterVO> listBy(long accountId) {
SearchCriteria<DomainRouterVO> sc = AllFieldsSearch.create();

View File

@ -1751,18 +1751,18 @@ CREATE TABLE `cloud`.`ovs_tunnel`(
PRIMARY KEY(`from`, `to`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `cloud`.`ovs_tunnel_account`(
CREATE TABLE `cloud`.`ovs_tunnel_network`(
`id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT,
`from` bigint unsigned COMMENT 'from host id',
`to` bigint unsigned COMMENT 'to host id',
`account` bigint unsigned COMMENT 'account',
`network_id` bigint unsigned COMMENT 'network identifier',
`key` int unsigned COMMENT 'gre key',
`port_name` varchar(32) COMMENT 'in port on open vswitch',
`state` varchar(16) default 'FAILED' COMMENT 'result of tunnel creatation',
PRIMARY KEY(`from`, `to`, `account`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `cloud`.`ovs_tunnel_account` (`from`, `to`, `account`, `key`, `port_name`, `state`) VALUES (0, 0, 0, 0, 'lock', 'SUCCESS');
INSERT INTO `cloud`.`ovs_tunnel_network` (`from`, `to`, `network_id`, `key`, `port_name`, `state`) VALUES (0, 0, 0, 0, 'lock', 'SUCCESS');
CREATE TABLE `cloud`.`ovs_vlan_mapping_dirty`(
`id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT,