mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
adding distributed routing support for KVM OVS
some check style error fixes
This commit is contained in:
parent
423a748807
commit
36541a2f4c
@ -78,6 +78,8 @@ import com.cloud.agent.api.OvsDestroyTunnelCommand;
|
|||||||
import com.cloud.agent.api.OvsFetchInterfaceAnswer;
|
import com.cloud.agent.api.OvsFetchInterfaceAnswer;
|
||||||
import com.cloud.agent.api.OvsFetchInterfaceCommand;
|
import com.cloud.agent.api.OvsFetchInterfaceCommand;
|
||||||
import com.cloud.agent.api.OvsSetupBridgeCommand;
|
import com.cloud.agent.api.OvsSetupBridgeCommand;
|
||||||
|
import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand;
|
||||||
|
import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand;
|
||||||
import com.cloud.agent.api.PingCommand;
|
import com.cloud.agent.api.PingCommand;
|
||||||
import com.cloud.agent.api.PingRoutingCommand;
|
import com.cloud.agent.api.PingRoutingCommand;
|
||||||
import com.cloud.agent.api.PingRoutingWithNwGroupsCommand;
|
import com.cloud.agent.api.PingRoutingWithNwGroupsCommand;
|
||||||
@ -1360,6 +1362,10 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||||||
return execute((OvsCreateTunnelCommand)cmd);
|
return execute((OvsCreateTunnelCommand)cmd);
|
||||||
} else if (cmd instanceof OvsDestroyTunnelCommand) {
|
} else if (cmd instanceof OvsDestroyTunnelCommand) {
|
||||||
return execute((OvsDestroyTunnelCommand)cmd);
|
return execute((OvsDestroyTunnelCommand)cmd);
|
||||||
|
} else if (cmd instanceof OvsVpcPhysicalTopologyConfigCommand) {
|
||||||
|
return execute((OvsVpcPhysicalTopologyConfigCommand) cmd);
|
||||||
|
} else if (cmd instanceof OvsVpcRoutingPolicyConfigCommand) {
|
||||||
|
return execute((OvsVpcRoutingPolicyConfigCommand) cmd);
|
||||||
} else {
|
} else {
|
||||||
s_logger.warn("Unsupported command ");
|
s_logger.warn("Unsupported command ");
|
||||||
return Answer.createUnsupportedCommandAnswer(cmd);
|
return Answer.createUnsupportedCommandAnswer(cmd);
|
||||||
@ -1401,6 +1407,47 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv
|
|||||||
return new Answer(cmd, true, null);
|
return new Answer(cmd, true, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Answer execute(OvsVpcPhysicalTopologyConfigCommand cmd) {
|
||||||
|
|
||||||
|
String bridge = cmd.getBridgeName();
|
||||||
|
try {
|
||||||
|
Script command = new Script(_ovsTunnelPath, _timeout, s_logger);
|
||||||
|
command.add("configure_ovs_bridge_for_network_topology");
|
||||||
|
command.add("--bridge", bridge);
|
||||||
|
command.add("--config", cmd.getVpcConfigInJson());
|
||||||
|
|
||||||
|
String result = command.execute();
|
||||||
|
if (result.equalsIgnoreCase("SUCCESS")) {
|
||||||
|
return new Answer(cmd, true, result);
|
||||||
|
} else {
|
||||||
|
return new Answer(cmd, false, result);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.warn("caught exception while updating host with latest routing polcies", e);
|
||||||
|
return new Answer(cmd, false, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Answer execute(OvsVpcRoutingPolicyConfigCommand cmd) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Script command = new Script(_ovsTunnelPath, _timeout, s_logger);
|
||||||
|
command.add("configure_ovs_bridge_for_routing_policies");
|
||||||
|
command.add("--bridge", cmd.getBridgeName());
|
||||||
|
command.add("--config", cmd.getVpcConfigInJson());
|
||||||
|
|
||||||
|
String result = command.execute();
|
||||||
|
if (result.equalsIgnoreCase("SUCCESS")) {
|
||||||
|
return new Answer(cmd, true, result);
|
||||||
|
} else {
|
||||||
|
return new Answer(cmd, false, result);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
s_logger.warn("caught exception while updating host with latest VPC topology", e);
|
||||||
|
return new Answer(cmd, false, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private synchronized void destroyTunnelNetwork(String bridge) {
|
private synchronized void destroyTunnelNetwork(String bridge) {
|
||||||
try {
|
try {
|
||||||
findOrCreateTunnelNetwork(bridge);
|
findOrCreateTunnelNetwork(bridge);
|
||||||
|
|||||||
@ -88,7 +88,6 @@ import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
|||||||
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
|
|
||||||
import com.cloud.agent.IAgentControl;
|
import com.cloud.agent.IAgentControl;
|
||||||
|
|
||||||
import com.cloud.agent.api.Answer;
|
import com.cloud.agent.api.Answer;
|
||||||
import com.cloud.agent.api.AttachIsoCommand;
|
import com.cloud.agent.api.AttachIsoCommand;
|
||||||
import com.cloud.agent.api.AttachVolumeAnswer;
|
import com.cloud.agent.api.AttachVolumeAnswer;
|
||||||
@ -149,6 +148,7 @@ import com.cloud.agent.api.OvsSetTagAndFlowAnswer;
|
|||||||
import com.cloud.agent.api.OvsSetTagAndFlowCommand;
|
import com.cloud.agent.api.OvsSetTagAndFlowCommand;
|
||||||
import com.cloud.agent.api.OvsSetupBridgeCommand;
|
import com.cloud.agent.api.OvsSetupBridgeCommand;
|
||||||
import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand;
|
import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand;
|
||||||
|
import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand;
|
||||||
import com.cloud.agent.api.PerformanceMonitorAnswer;
|
import com.cloud.agent.api.PerformanceMonitorAnswer;
|
||||||
import com.cloud.agent.api.PerformanceMonitorCommand;
|
import com.cloud.agent.api.PerformanceMonitorCommand;
|
||||||
import com.cloud.agent.api.PingCommand;
|
import com.cloud.agent.api.PingCommand;
|
||||||
|
|||||||
@ -18,7 +18,6 @@ package com.cloud.agent.api;
|
|||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This command represents logical view of VM's connectivity in VPC.
|
* This command represents logical view of VM's connectivity in VPC.
|
||||||
|
|||||||
@ -16,11 +16,25 @@
|
|||||||
// under the License.
|
// under the License.
|
||||||
package com.cloud.network.ovs;
|
package com.cloud.network.ovs;
|
||||||
|
|
||||||
import com.amazonaws.services.ec2.model.NetworkAcl;
|
import com.cloud.agent.api.Answer;
|
||||||
import com.cloud.agent.api.*;
|
import com.cloud.agent.api.Command;
|
||||||
|
import com.cloud.agent.api.OvsCreateTunnelAnswer;
|
||||||
|
import com.cloud.agent.api.OvsCreateTunnelCommand;
|
||||||
|
import com.cloud.agent.api.OvsDestroyBridgeCommand;
|
||||||
|
import com.cloud.agent.api.OvsDestroyTunnelCommand;
|
||||||
|
import com.cloud.agent.api.OvsFetchInterfaceAnswer;
|
||||||
|
import com.cloud.agent.api.OvsFetchInterfaceCommand;
|
||||||
|
import com.cloud.agent.api.OvsSetupBridgeCommand;
|
||||||
|
import com.cloud.agent.api.OvsVpcPhysicalTopologyConfigCommand;
|
||||||
|
import com.cloud.agent.api.OvsVpcRoutingPolicyConfigCommand;
|
||||||
import com.cloud.network.dao.NetworkDao;
|
import com.cloud.network.dao.NetworkDao;
|
||||||
import com.cloud.network.dao.NetworkVO;
|
import com.cloud.network.dao.NetworkVO;
|
||||||
import com.cloud.network.vpc.*;
|
import com.cloud.network.vpc.NetworkACLVO;
|
||||||
|
import com.cloud.network.vpc.NetworkACLItemDao;
|
||||||
|
import com.cloud.network.vpc.NetworkACLItemVO;
|
||||||
|
import com.cloud.network.vpc.dao.VpcDao;
|
||||||
|
import com.cloud.network.vpc.VpcManager;
|
||||||
|
import com.cloud.network.vpc.VpcVO;
|
||||||
import com.cloud.network.vpc.dao.NetworkACLDao;
|
import com.cloud.network.vpc.dao.NetworkACLDao;
|
||||||
import com.cloud.vm.dao.VMInstanceDao;
|
import com.cloud.vm.dao.VMInstanceDao;
|
||||||
import com.cloud.vm.Nic;
|
import com.cloud.vm.Nic;
|
||||||
@ -63,7 +77,6 @@ import com.cloud.network.ovs.dao.OvsTunnelInterfaceVO;
|
|||||||
import com.cloud.network.ovs.dao.OvsTunnelNetworkDao;
|
import com.cloud.network.ovs.dao.OvsTunnelNetworkDao;
|
||||||
import com.cloud.network.ovs.dao.OvsTunnelNetworkVO;
|
import com.cloud.network.ovs.dao.OvsTunnelNetworkVO;
|
||||||
import com.cloud.network.ovs.dao.OvsTunnel;
|
import com.cloud.network.ovs.dao.OvsTunnel;
|
||||||
import com.cloud.network.vpc.dao.VpcDao;
|
|
||||||
import com.cloud.utils.component.ManagerBase;
|
import com.cloud.utils.component.ManagerBase;
|
||||||
import com.cloud.utils.concurrency.NamedThreadFactory;
|
import com.cloud.utils.concurrency.NamedThreadFactory;
|
||||||
import com.cloud.utils.db.DB;
|
import com.cloud.utils.db.DB;
|
||||||
|
|||||||
@ -174,6 +174,7 @@ def _build_flow_expr(**kwargs):
|
|||||||
dl_dst = 'dl_dst' in kwargs and ",dl_dst=%s" % kwargs['dl_dst'] or ''
|
dl_dst = 'dl_dst' in kwargs and ",dl_dst=%s" % kwargs['dl_dst'] or ''
|
||||||
nw_src = 'nw_src' in kwargs and ",nw_src=%s" % kwargs['nw_src'] or ''
|
nw_src = 'nw_src' in kwargs and ",nw_src=%s" % kwargs['nw_src'] or ''
|
||||||
nw_dst = 'nw_dst' in kwargs and ",nw_dst=%s" % kwargs['nw_dst'] or ''
|
nw_dst = 'nw_dst' in kwargs and ",nw_dst=%s" % kwargs['nw_dst'] or ''
|
||||||
|
table = 'table' in kwargs and ",table=%s" % kwargs['table'] or ''
|
||||||
proto = 'proto' in kwargs and ",%s" % kwargs['proto'] or ''
|
proto = 'proto' in kwargs and ",%s" % kwargs['proto'] or ''
|
||||||
ip = ('nw_src' in kwargs or 'nw_dst' in kwargs) and ',ip' or ''
|
ip = ('nw_src' in kwargs or 'nw_dst' in kwargs) and ',ip' or ''
|
||||||
flow = (flow + in_port + dl_type + dl_src + dl_dst +
|
flow = (flow + in_port + dl_type + dl_src + dl_dst +
|
||||||
@ -217,3 +218,228 @@ def del_all_flows(bridge):
|
|||||||
def del_port(bridge, port):
|
def del_port(bridge, port):
|
||||||
delPort = [VSCTL_PATH, "del-port", bridge, port]
|
delPort = [VSCTL_PATH, "del-port", bridge, port]
|
||||||
do_cmd(delPort)
|
do_cmd(delPort)
|
||||||
|
|
||||||
|
|
||||||
|
def get_network_id_for_vif(vif_name):
|
||||||
|
domain_id, device_id = vif_name[3:len(vif_name)].split(".")
|
||||||
|
dom_uuid = do_cmd([XE_PATH, "vm-list", "dom-id=%s" % domain_id, "--minimal"])
|
||||||
|
vif_uuid = do_cmd([XE_PATH, "vif-list", "vm-uuid=%s" % dom_uuid, "device=%s" % device_id, "--minimal"])
|
||||||
|
vnet = do_cmd([XE_PATH, "vif-param-get", "uuid=%s" % vif_uuid, "param-name=other-config",
|
||||||
|
"param-key=cloudstack-network-id"])
|
||||||
|
return vnet
|
||||||
|
|
||||||
|
def get_network_id_for_tunnel_port(tunnelif_name):
|
||||||
|
vnet = do_cmd([VSCTL_PATH, "get", "interface", tunnelif_name, "options:cloudstack-network-id"])
|
||||||
|
return vnet
|
||||||
|
|
||||||
|
def clear_flooding_rules_for_port(bridge, ofport):
|
||||||
|
del_flows(bridge, in_port=ofport, table=2)
|
||||||
|
|
||||||
|
def add_flooding_rules_for_port(bridge, in_ofport, out_ofports):
|
||||||
|
action = "".join("output:%s," %ofport for ofport in out_ofports)[:-1]
|
||||||
|
add_flow(bridge, priority=1100, in_port=in_ofport, table=1, actions=action)
|
||||||
|
|
||||||
|
def get_ofport_for_vif(vif_name):
|
||||||
|
return do_cmd([VSCTL_PATH, "get", "interface", vif_name, "ofport"])
|
||||||
|
|
||||||
|
def get_macaddress_of_vif(vif_name):
|
||||||
|
domain_id, device_id = vif_name[3:len(vif_name)].split(".")
|
||||||
|
dom_uuid = do_cmd([XE_PATH, "vm-list", "dom-id=%s" % domain_id, "--minimal"])
|
||||||
|
vif_uuid = do_cmd([XE_PATH, "vif-list", "vm-uuid=%s" % dom_uuid, "device=%s" % device_id, "--minimal"])
|
||||||
|
mac = do_cmd([XE_PATH, "vif-param-get", "uuid=%s" % vif_uuid, "param-name=MAC"])
|
||||||
|
return mac
|
||||||
|
|
||||||
|
def get_vif_name_from_macaddress(macaddress):
|
||||||
|
vif_uuid = do_cmd([XE_PATH, "vif-list", "MAC=%s" % macaddress, "--minimal"])
|
||||||
|
vif_device_id = do_cmd([XE_PATH, "vif-param-get", "uuid=%s" % vif_uuid, "param-name=device"])
|
||||||
|
vm_uuid = do_cmd([XE_PATH, "vif-param-get", "uuid=%s" % vif_uuid, "param-name=vm-uuid"])
|
||||||
|
vm_domain_id = do_cmd([XE_PATH, "vm-param-get", "uuid=%s" % vm_uuid, "param-name=dom-id"])
|
||||||
|
return "vif"+vm_domain_id+"."+vif_device_id
|
||||||
|
|
||||||
|
def add_mac_lookup_table_entry(bridge, mac_address, out_of_port):
|
||||||
|
add_flow(bridge, priority=1100, dl_dst=mac_address, table=1, actions="output:%s" % out_of_port)
|
||||||
|
|
||||||
|
def delete_mac_lookup_table_entry(bridge, mac_address):
|
||||||
|
del_flows(bridge, dl_dst=mac_address, table=1)
|
||||||
|
|
||||||
|
def add_ip_lookup_table_entry(bridge, ip, dst_tier_gateway_mac, dst_vm_mac):
|
||||||
|
action_str = "mod_dl_sr:%s" % dst_tier_gateway_mac + ",mod_dl_dst:%s" % dst_vm_mac +",resubmit(,5)"
|
||||||
|
addflow = [OFCTL_PATH, "add-flow", bridge, "table=4", "nw_dst=%s" % ip, "actions=%s" %action_str]
|
||||||
|
do_cmd(addflow)
|
||||||
|
|
||||||
|
def get_vms_on_host(vpc, host_id):
|
||||||
|
all_vms = vpc.vms
|
||||||
|
vms_on_host = []
|
||||||
|
for vm in all_vms:
|
||||||
|
if vm.hostid == host_id:
|
||||||
|
vms_on_host.append(vm)
|
||||||
|
return vms_on_host
|
||||||
|
|
||||||
|
def get_network_details(vpc, network_uuid):
|
||||||
|
tiers = vpc.tiers
|
||||||
|
for tier in tiers:
|
||||||
|
if tier.networkuuid == network_uuid:
|
||||||
|
return tier
|
||||||
|
return None
|
||||||
|
|
||||||
|
class jsonLoader(object):
|
||||||
|
def __init__(self, obj):
|
||||||
|
for k in obj:
|
||||||
|
v = obj[k]
|
||||||
|
if isinstance(v, dict):
|
||||||
|
setattr(self, k, jsonLoader(v))
|
||||||
|
elif isinstance(v, (list, tuple)):
|
||||||
|
if len(v) > 0 and isinstance(v[0], dict):
|
||||||
|
setattr(self, k, [jsonLoader(elem) for elem in v])
|
||||||
|
else:
|
||||||
|
setattr(self, k, v)
|
||||||
|
else:
|
||||||
|
setattr(self, k, v)
|
||||||
|
|
||||||
|
def __getattr__(self, val):
|
||||||
|
if val in self.__dict__:
|
||||||
|
return self.__dict__[val]
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return '{%s}' % str(', '.join('%s : %s' % (k, repr(v)) for (k, v)
|
||||||
|
in self.__dict__.iteritems()))
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return '{%s}' % str(', '.join('%s : %s' % (k, repr(v)) for (k, v)
|
||||||
|
in self.__dict__.iteritems()))
|
||||||
|
|
||||||
|
def configure_bridge_for_network_topology(bridge, this_host_id, json_config):
|
||||||
|
vpconfig = jsonLoader(json.loads(json_config)).vpc
|
||||||
|
|
||||||
|
if vpconfig is None:
|
||||||
|
logging.debug("WARNING:Can't find VPC info in json config file")
|
||||||
|
return "FAILURE:IMPROPER_JSON_CONFG_FILE"
|
||||||
|
|
||||||
|
# get the list of Vm's in the VPC from the JSON config
|
||||||
|
this_host_vms = get_vms_on_host(vpconfig, this_host_id)
|
||||||
|
|
||||||
|
for vm in this_host_vms:
|
||||||
|
for nic in vm.nics:
|
||||||
|
mac_addr = nic.macaddress
|
||||||
|
ip = nic.ipaddress
|
||||||
|
vif_name = get_vif_name_from_macaddress(mac_addr)
|
||||||
|
of_port = get_ofport_for_vif(vif_name)
|
||||||
|
network = get_network_details(vpconfig, nic.networkuuid)
|
||||||
|
|
||||||
|
# Add flow rule in L2 look up table, if the destination mac = MAC of the nic send packet on the found OFPORT
|
||||||
|
add_mac_lookup_table_entry(bridge, mac_addr, of_port)
|
||||||
|
|
||||||
|
# Add flow rule in L3 look up table: if the destination IP = VM's IP then modify the packet
|
||||||
|
# to set DST MAC = VM's MAC, SRC MAC=tier gateway MAC and send to egress table
|
||||||
|
add_ip_lookup_table_entry(bridge, ip, network.gatewaymac, mac_addr)
|
||||||
|
|
||||||
|
# Add flow entry to send with intra tier traffic from the NIC to L2 lookup path)
|
||||||
|
addflow = [OFCTL_PATH, "add-flow", bridge, "table=0", "in_port=%s" % of_port,
|
||||||
|
"nw_dst=%s" %network.cidr, "actions=resubmit(,1)"]
|
||||||
|
do_cmd(addflow)
|
||||||
|
|
||||||
|
#add flow entry to send inter-tier traffic from the NIC to egress ACL table(to L3 lookup path)
|
||||||
|
addflow = [OFCTL_PATH, "add-flow", bridge, "table=0", "in_port=%s" % of_port,
|
||||||
|
"dl_dst=%s" %network.gatewaymac, "nw_dst=%s" %vpconfig.cidr, "actions=resubmit(,3)"]
|
||||||
|
do_cmd(addflow)
|
||||||
|
|
||||||
|
# get the list of hosts on which VPC spans from the JSON config
|
||||||
|
vpc_spanning_hosts = vpconfig.hosts
|
||||||
|
|
||||||
|
for host in vpc_spanning_hosts:
|
||||||
|
if this_host_id == host.hostid:
|
||||||
|
continue
|
||||||
|
other_host_vms = get_vms_on_host(vpconfig, host.hostid)
|
||||||
|
for vm in other_host_vms:
|
||||||
|
for nic in vm.nics:
|
||||||
|
mac_addr = nic.macaddress
|
||||||
|
ip = nic.ipaddress
|
||||||
|
network = get_network_details(vpconfig, nic.networkuuid)
|
||||||
|
gre_key = network.grekey
|
||||||
|
|
||||||
|
# generate tunnel name from tunnel naming convention
|
||||||
|
tunnel_name = "t%s-%s-%s" % (gre_key, this_host_id, host.hostid)
|
||||||
|
of_port = get_ofport_for_vif(tunnel_name)
|
||||||
|
|
||||||
|
# Add flow rule in L2 look up table, if the destination mac = MAC of the nic send packet tunnel port
|
||||||
|
add_mac_lookup_table_entry(bridge, mac_addr, of_port)
|
||||||
|
|
||||||
|
# Add flow tule in L3 look up table: if the destination IP = VM's IP then modify the packet
|
||||||
|
# set DST MAC = VM's MAC, SRC MAC=tier gateway MAC and send to egress table
|
||||||
|
add_ip_lookup_table_entry(bridge, ip, network.gatewaymac, mac_addr)
|
||||||
|
|
||||||
|
return "SUCCESS: successfully configured bridge as per the VPC topology"
|
||||||
|
|
||||||
|
def get_acl(vpcconfig, required_acl_id):
|
||||||
|
acls = vpcconfig.acls
|
||||||
|
for acl in acls:
|
||||||
|
if acl.id == required_acl_id:
|
||||||
|
return acl
|
||||||
|
return None
|
||||||
|
|
||||||
|
def configure_ovs_bridge_for_routing_policies(bridge, json_config):
|
||||||
|
vpconfig = jsonLoader(json.loads(json_config)).vpc
|
||||||
|
|
||||||
|
if vpconfig is None:
|
||||||
|
logging.debug("WARNING:Can't find VPC info in json config file")
|
||||||
|
return "FAILURE:IMPROPER_JSON_CONFG_FILE"
|
||||||
|
|
||||||
|
# First flush current egress ACL's before re-applying the ACL's
|
||||||
|
del_flows(bridge, table=3)
|
||||||
|
|
||||||
|
egress_rules_added = False
|
||||||
|
ingress_rules_added = False
|
||||||
|
|
||||||
|
tiers = vpconfig.tiers
|
||||||
|
for tier in tiers:
|
||||||
|
tier_cidr = tier.cidr
|
||||||
|
acl = get_acl(vpconfig, tier.aclid)
|
||||||
|
acl_items = acl.aclitems
|
||||||
|
|
||||||
|
for acl_item in acl_items:
|
||||||
|
number = acl_item.number
|
||||||
|
action = acl_item.action
|
||||||
|
direction = acl_item.direction
|
||||||
|
source_port_start = acl_item.sourceportstart
|
||||||
|
source_port_end = acl_item.sourceportend
|
||||||
|
protocol = acl_item.protocol
|
||||||
|
source_cidrs = acl_item.sourcecidrs
|
||||||
|
acl_priority = 1000 + number
|
||||||
|
for source_cidr in source_cidrs:
|
||||||
|
if direction is "ingress":
|
||||||
|
ingress_rules_added = True
|
||||||
|
# add flow rule to do action (allow/deny) for flows where source IP of the packet is in
|
||||||
|
# source_cidr and destination ip is in tier_cidr
|
||||||
|
port = source_port_start
|
||||||
|
while (port < source_port_end):
|
||||||
|
if action is "deny":
|
||||||
|
add_flow(bridge, priority= acl_priority, table=5, nw_src=source_cidr, nw_dst=tier_cidr, tp_dst=port,
|
||||||
|
nw_proto=protocol, actions='drop')
|
||||||
|
if action is "allow":
|
||||||
|
add_flow(bridge, priority= acl_priority,table=5, nw_src=source_cidr, nw_dst=tier_cidr, tp_dst=port,
|
||||||
|
nw_proto=protocol, actions='resubmit(,1)')
|
||||||
|
port = port + 1
|
||||||
|
|
||||||
|
elif direction in "egress":
|
||||||
|
egress_rules_added = True
|
||||||
|
# add flow rule to do action (allow/deny) for flows where destination IP of the packet is in
|
||||||
|
# source_cidr and source ip is in tier_cidr
|
||||||
|
port = source_port_start
|
||||||
|
while (port < source_port_end):
|
||||||
|
if action is "deny":
|
||||||
|
add_flow(bridge, priority= acl_priority, table=5, nw_src=tier_cidr, nw_dst=source_cidr, tp_dst=port,
|
||||||
|
nw_proto=protocol, actions='drop')
|
||||||
|
if action is "allow":
|
||||||
|
add_flow(bridge, priority= acl_priority, table=5, nw_src=tier_cidr, nw_dst=source_cidr, tp_dst=port,
|
||||||
|
nw_proto=protocol, actions='resubmit(,1)')
|
||||||
|
port = port + 1
|
||||||
|
|
||||||
|
if egress_rules_added is False:
|
||||||
|
# add a default rule in egress table to forward packet to L3 lookup table
|
||||||
|
add_flow(bridge, priority=0, table=3, actions='resubmit(,4)')
|
||||||
|
|
||||||
|
if ingress_rules_added is False:
|
||||||
|
# add a default rule in egress table drop packets
|
||||||
|
add_flow(bridge, priority=0, table=5, actions='drop')
|
||||||
|
|||||||
@ -27,6 +27,7 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
|
import simplejson as json
|
||||||
from optparse import OptionParser, OptionGroup, OptParseError, BadOptionError, OptionError, OptionConflictError, OptionValueError
|
from optparse import OptionParser, OptionGroup, OptParseError, BadOptionError, OptionError, OptionConflictError, OptionValueError
|
||||||
|
|
||||||
from time import localtime as _localtime, asctime as _asctime
|
from time import localtime as _localtime, asctime as _asctime
|
||||||
@ -72,6 +73,58 @@ def setup_ovs_bridge(bridge, key, cs_host_id):
|
|||||||
logging.debug("Setup_ovs_bridge completed with result:%s" % result)
|
logging.debug("Setup_ovs_bridge completed with result:%s" % result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@echo
|
||||||
|
def setup_ovs_bridge_for_distributed_routing(bridge, cs_host_id):
|
||||||
|
|
||||||
|
res = lib.check_switch()
|
||||||
|
if res != "SUCCESS":
|
||||||
|
return "FAILURE:%s" % res
|
||||||
|
|
||||||
|
logging.debug("About to manually create the bridge:%s" % bridge)
|
||||||
|
res = lib.do_cmd([lib.VSCTL_PATH, "--", "--may-exist", "add-br", bridge])
|
||||||
|
logging.debug("Bridge has been manually created:%s" % res)
|
||||||
|
|
||||||
|
# Non empty result means something went wrong
|
||||||
|
if res:
|
||||||
|
result = "FAILURE:%s" % res
|
||||||
|
else:
|
||||||
|
# Verify the bridge actually exists
|
||||||
|
res = lib.do_cmd([lib.VSCTL_PATH, "list", "bridge", bridge])
|
||||||
|
|
||||||
|
res = lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other_config:is-ovs_vpc_distributed_vr_network=True"])
|
||||||
|
conf_hosts = lib.do_cmd([lib.VSCTL_PATH, "get","bridge", bridge,"other:ovs-host-setup"])
|
||||||
|
conf_hosts = cs_host_id + (conf_hosts and ',%s' % conf_hosts or '')
|
||||||
|
lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge,
|
||||||
|
"other_config:ovs-host-setup=%s" % conf_hosts])
|
||||||
|
|
||||||
|
# add a default flow rule to send broadcast and multi-cast packets to L2 flooding table
|
||||||
|
lib.add_flow(bridge, priority=1000, dl_dst='ff:ff:ff:ff:ff:ff', table=0, actions='resubmit(,2)')
|
||||||
|
lib.add_flow(bridge, priority=1000, nw_dst='224.0.0.0/24', table=0, actions='resubmit(,2)')
|
||||||
|
|
||||||
|
# add a default flow rule to send uni-cast traffic to L2 lookup table
|
||||||
|
lib.add_flow(bridge, priority=0, table=0, actions='resubmit(,1)')
|
||||||
|
|
||||||
|
# add a default rule to send unknown mac address to L2 flooding table
|
||||||
|
lib.add_flow(bridge, priority=0, table=1, actions='resubmit(,2)')
|
||||||
|
|
||||||
|
# add a default rule in L2 flood table to drop packet
|
||||||
|
lib.add_flow(bridge, priority=0, table=2, actions='drop')
|
||||||
|
|
||||||
|
# add a default rule in egress table to forward packet to L3 lookup table
|
||||||
|
lib.add_flow(bridge, priority=0, table=3, actions='resubmit(,4)')
|
||||||
|
|
||||||
|
# add a default rule in L3 lookup table to forward packet to L2 lookup table
|
||||||
|
lib.add_flow(bridge, priority=0, table=4, actions='resubmit(,1)')
|
||||||
|
|
||||||
|
# add a default rule in ingress table to drop in bound packets
|
||||||
|
lib.add_flow(bridge, priority=0, table=5, actions='drop')
|
||||||
|
|
||||||
|
result = "SUCCESS: successfully setup bridge with flow rules"
|
||||||
|
|
||||||
|
logging.debug("Setup_ovs_bridge completed with result:%s" % result)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
def destroy_ovs_bridge(bridge):
|
def destroy_ovs_bridge(bridge):
|
||||||
|
|
||||||
res = lib.check_switch()
|
res = lib.check_switch()
|
||||||
@ -163,12 +216,30 @@ def create_tunnel(bridge, remote_ip, key, src_host, dst_host):
|
|||||||
# Ensure no trailing LF
|
# Ensure no trailing LF
|
||||||
if tun_ofport.endswith('\n'):
|
if tun_ofport.endswith('\n'):
|
||||||
tun_ofport = tun_ofport[:-1]
|
tun_ofport = tun_ofport[:-1]
|
||||||
|
|
||||||
|
ovs_tunnel_network = lib.do_cmd([lib.VSCTL_PATH, "get", "bridge", bridge, "other_config:is-ovs-tun-network"])
|
||||||
|
ovs_vpc_distributed_vr_network = lib.do_cmd([lib.VSCTL_PATH, "get", "bridge", bridge,
|
||||||
|
"other_config:is-ovs_vpc_distributed_vr_network"])
|
||||||
|
|
||||||
|
if ovs_tunnel_network == 'True':
|
||||||
# add flow entryies for dropping broadcast coming in from gre tunnel
|
# add flow entryies for dropping broadcast coming in from gre tunnel
|
||||||
lib.add_flow(bridge, priority=1000, in_port=tun_ofport,
|
lib.add_flow(bridge, priority=1000, in_port=tun_ofport,
|
||||||
dl_dst='ff:ff:ff:ff:ff:ff', actions='drop')
|
dl_dst='ff:ff:ff:ff:ff:ff', actions='drop')
|
||||||
lib.add_flow(bridge, priority=1000, in_port=tun_ofport,
|
lib.add_flow(bridge, priority=1000, in_port=tun_ofport,
|
||||||
nw_dst='224.0.0.0/24', actions='drop')
|
nw_dst='224.0.0.0/24', actions='drop')
|
||||||
drop_flow_setup = True
|
drop_flow_setup = True
|
||||||
|
|
||||||
|
if ovs_vpc_distributed_vr_network == 'True':
|
||||||
|
# add flow rules for dropping broadcast coming in from tunnel ports
|
||||||
|
lib.add_flow(bridge, priority=1000, in_port=tun_ofport, table=0,
|
||||||
|
dl_dst='ff:ff:ff:ff:ff:ff', actions='drop')
|
||||||
|
lib.add_flow(bridge, priority=1000, in_port=tun_ofport, table=0,
|
||||||
|
nw_dst='224.0.0.0/24', actions='drop')
|
||||||
|
|
||||||
|
# add flow rule to send the traffic from tunnel ports to L2 switching table only
|
||||||
|
lib.add_flow(bridge, priority=1000, in_port=tun_ofport, table=0, actions='resubmit(,1)')
|
||||||
|
lib.do_cmd([lib.VSCTL_PATH, "set", "interface", name, "options:cloudstack-network-id=%s" % network_uuid])
|
||||||
|
|
||||||
logging.debug("Broadcast drop rules added")
|
logging.debug("Broadcast drop rules added")
|
||||||
# return "SUCCESS:%s" % name
|
# return "SUCCESS:%s" % name
|
||||||
return 'true'
|
return 'true'
|
||||||
@ -210,6 +281,7 @@ if __name__ == '__main__':
|
|||||||
parser.add_option("--src_host", dest="src_host")
|
parser.add_option("--src_host", dest="src_host")
|
||||||
parser.add_option("--dst_host", dest="dst_host")
|
parser.add_option("--dst_host", dest="dst_host")
|
||||||
parser.add_option("--iface_name", dest="iface_name")
|
parser.add_option("--iface_name", dest="iface_name")
|
||||||
|
parser.ad_option("--config", dest="config")
|
||||||
(option, args) = parser.parse_args()
|
(option, args) = parser.parse_args()
|
||||||
if len(args) == 0:
|
if len(args) == 0:
|
||||||
logging.debug("No command to execute")
|
logging.debug("No command to execute")
|
||||||
@ -223,6 +295,12 @@ if __name__ == '__main__':
|
|||||||
create_tunnel(option.bridge, option.remote_ip, option.key, option.src_host, option.dst_host)
|
create_tunnel(option.bridge, option.remote_ip, option.key, option.src_host, option.dst_host)
|
||||||
elif cmd == "destroy_tunnel":
|
elif cmd == "destroy_tunnel":
|
||||||
destroy_tunnel(option.bridge, option.iface_name)
|
destroy_tunnel(option.bridge, option.iface_name)
|
||||||
|
elif cmd == "setup_ovs_bridge_for_distributed_routing":
|
||||||
|
setup_ovs_bridge_for_distributed_routing(bridge, cs_host_id)
|
||||||
|
elif cmd == "configure_ovs_bridge_for_network_topology":
|
||||||
|
configure_bridge_for_network_topology(brdige, cs_host_id, config)
|
||||||
|
elif cmd == "configure_ovs_bridge_for_routing_policies":
|
||||||
|
configure_ovs_bridge_for_routing_policies(bridge, config)
|
||||||
else:
|
else:
|
||||||
logging.debug("Unknown command: " + cmd)
|
logging.debug("Unknown command: " + cmd)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user