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] | ||||||
|         # add flow entryies for dropping broadcast coming in from gre tunnel | 
 | ||||||
|         lib.add_flow(bridge, priority=1000, in_port=tun_ofport, |         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 | ||||||
|  |             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