Exemple #1
0
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
Exemple #2
0
def destroy_ovs_bridge(bridge):

    res = lib.check_switch()
    if res != "SUCCESS":
#        return res
        return 'false'

    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
        result = 'false'
    else:
#        result = "SUCCESS:%s" % bridge
        result = 'true'

    logging.debug("Destroy_ovs_bridge completed with result:%s" % result)
    return result
Exemple #3
0
def setup_ovs_bridge(bridge, key, cs_host_id):

    res = lib.check_switch()
    if res != "SUCCESS":
        #return "FAILURE:%s" % res
	return 'false'

    logging.debug("About to manually create the bridge:%s" % bridge)
    #set gre_key to bridge
    res = lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge,
                                     "other_config:gre_key=%s" % key])

    # enable stp
    lib.do_cmd([lib.VSCTL_PATH, "set", "Bridge", bridge, "stp_enable=true"])

    logging.debug("Bridge has been manually created:%s" % res)
    if res:
#        result = "FAILURE:%s" % res
	result = 'false'
    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
            result = 'true'
        else:
#            result = "FAILURE:%s" % res
            result = 'false'

	lib.do_cmd([lib.VSCTL_PATH, "set", "bridge", bridge, "other_config:is-ovs-tun-network=True"])
	#get list of hosts using this bridge
        conf_hosts = lib.do_cmd([lib.VSCTL_PATH, "get","bridge", bridge,"other_config:ovs-host-setup"])
	#add cs_host_id to list of hosts using this bridge
        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])

    logging.debug("Setup_ovs_bridge completed with result:%s" % result)
    return result
Exemple #4
0
def create_tunnel(bridge, remote_ip, key, src_host, dst_host):

    logging.debug("Entering create_tunnel")

    res = lib.check_switch()
    if res != "SUCCESS":
        logging.debug("Openvswitch running: NO")
#        return "FAILURE:%s" % res
        return 'false'

    # We need to keep the name below 14 characters
    # src and target are enough - consider a fixed length hash
    name = "t%s-%s-%s" % (key, src_host, dst_host)

    # Verify the 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"
        return 'false'

    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" % 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"
            return 'false'

        # 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 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"
            return 'false'

        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
        return 'true'
    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)
        # This will not cancel the original exception
        raise
Exemple #5
0
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' % eval(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
Exemple #6
0
def create_tunnel(bridge, remote_ip, key, src_host, dst_host):

    logging.debug("Entering create_tunnel")

    res = lib.check_switch()
    if res != "SUCCESS":
        logging.debug("Openvswitch running: NO")
        #        return "FAILURE:%s" % res
        return 'false'

    # We need to keep the name below 14 characters
    # src and target are enough - consider a fixed length hash
    name = "t%s-%s-%s" % (key, src_host, dst_host)

    # Verify the 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 str(res):
        logging.debug("WARNING:Can't find bridge %s for creating " +
                      "tunnel!" % bridge)
        #        return "FAILURE:NO_BRIDGE"
        return 'false'

    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" % 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(b',')
        if len(iface_list) != 1:
            logging.debug("WARNING: Unexpected output while verifying " +
                          "port %s on bridge %s" % (name, bridge))
            #            return "FAILURE:VERIFY_PORT_FAILED"
            return 'false'

        # 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 key in str(key_validation) or not remote_ip in str(
                ip_validation):
            logging.debug("WARNING: Unexpected output while verifying " +
                          "interface %s on bridge %s" % (name, bridge))
            #            return "FAILURE:VERIFY_INTERFACE_FAILED"
            return 'false'

        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(b'\n'):
            tun_ofport = tun_ofport[:-1]

        try:
            ovs_tunnel_network = lib.do_cmd([
                lib.VSCTL_PATH, "get", "bridge", bridge,
                "other_config:is-ovs-tun-network"
            ])
        except:
            ovs_tunnel_network = 'False'
        try:
            ovs_vpc_distributed_vr_network = lib.do_cmd([
                lib.VSCTL_PATH, "get", "bridge", bridge,
                "other_config:is-ovs_vpc_distributed_vr_network"
            ])
        except:
            ovs_vpc_distributed_vr_network = 'False'

        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')
            lib.add_flow(bridge,
                         priority=1000,
                         in_port=tun_ofport,
                         nw_dst='224.0.0.0/24',
                         actions='drop')
            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")
        #        return "SUCCESS:%s" % name
        return 'true'
    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)
        # This will not cancel the original exception
        raise