View file File name : openvswitch.py Content :""" Support for Open vSwitch - module with basic Open vSwitch commands. Suitable for setting up Openstack Neutron. :codeauthor: Jiri Kotlin <jiri.kotlin@ultimum.io> """ import logging import salt.utils.path log = logging.getLogger(__name__) def __virtual__(): """ Only load the module if Open vSwitch is installed """ if salt.utils.path.which("ovs-vsctl"): return "openvswitch" return (False, "Missing dependency: ovs-vsctl") def _param_may_exist(may_exist): """ Returns --may-exist parameter for Open vSwitch command. Args: may_exist: Boolean whether to use this parameter. Returns: String '--may-exist ' or empty string. """ if may_exist: return "--may-exist " else: return "" def _param_if_exists(if_exists): """ Returns --if-exist parameter for Open vSwitch command. Args: if_exists: Boolean whether to use this parameter. Returns: String '--if-exist ' or empty string. """ if if_exists: return "--if-exists " else: return "" def _retcode_to_bool(retcode): """ Evaulates Open vSwitch command`s retcode value. Args: retcode: Value of retcode field from response, should be 0, 1 or 2. Returns: True on 0, else False """ if retcode == 0: return True else: return False def _stdout_list_split(retcode, stdout="", splitstring="\n"): """ Evaulates Open vSwitch command`s retcode value. Args: retcode: Value of retcode field from response, should be 0, 1 or 2. stdout: Value of stdout filed from response. splitstring: String used to split the stdout default new line. Returns: List or False. """ if retcode == 0: ret = stdout.split(splitstring) return ret else: return False def bridge_list(): """ Lists all existing real and fake bridges. Returns: List of bridges (or empty list), False on failure. .. versionadded:: 2016.3.0 CLI Example: .. code-block:: bash salt '*' openvswitch.bridge_list """ cmd = "ovs-vsctl list-br" result = __salt__["cmd.run_all"](cmd) retcode = result["retcode"] stdout = result["stdout"] return _stdout_list_split(retcode, stdout) def bridge_exists(br): """ Tests whether bridge exists as a real or fake bridge. Returns: True if Bridge exists, else False. .. versionadded:: 2016.3.0 CLI Example: .. code-block:: bash salt '*' openvswitch.bridge_exists br0 """ cmd = "ovs-vsctl br-exists {}".format(br) result = __salt__["cmd.run_all"](cmd) retcode = result["retcode"] return _retcode_to_bool(retcode) def bridge_create(br, may_exist=True): """ Creates a new bridge. Args: br: A string - bridge name may_exist: Bool, if False - attempting to create a bridge that exists returns False. Returns: True on success, else False. .. versionadded:: 2016.3.0 CLI Example: .. code-block:: bash salt '*' openvswitch.bridge_create br0 """ param_may_exist = _param_may_exist(may_exist) cmd = "ovs-vsctl {1}add-br {0}".format(br, param_may_exist) result = __salt__["cmd.run_all"](cmd) return _retcode_to_bool(result["retcode"]) def bridge_delete(br, if_exists=True): """ Deletes bridge and all of its ports. Args: br: A string - bridge name if_exists: Bool, if False - attempting to delete a bridge that does not exist returns False. Returns: True on success, else False. .. versionadded:: 2016.3.0 CLI Example: .. code-block:: bash salt '*' openvswitch.bridge_delete br0 """ param_if_exists = _param_if_exists(if_exists) cmd = "ovs-vsctl {1}del-br {0}".format(br, param_if_exists) result = __salt__["cmd.run_all"](cmd) retcode = result["retcode"] return _retcode_to_bool(retcode) def port_add(br, port, may_exist=False, internal=False): """ Creates on bridge a new port named port. Returns: True on success, else False. Args: br: A string - bridge name port: A string - port name may_exist: Bool, if False - attempting to create a port that exists returns False. internal: A boolean to create an internal interface if one does not exist. .. versionadded:: 2016.3.0 CLI Example: .. code-block:: bash salt '*' openvswitch.port_add br0 8080 """ param_may_exist = _param_may_exist(may_exist) cmd = "ovs-vsctl {2}add-port {0} {1}".format(br, port, param_may_exist) if internal: cmd += " -- set interface {} type=internal".format(port) result = __salt__["cmd.run_all"](cmd) retcode = result["retcode"] return _retcode_to_bool(retcode) def port_remove(br, port, if_exists=True): """ Deletes port. Args: br: A string - bridge name (If bridge is None, port is removed from whatever bridge contains it) port: A string - port name. if_exists: Bool, if False - attempting to delete a por that does not exist returns False. (Default True) Returns: True on success, else False. .. versionadded:: 2016.3.0 CLI Example: .. code-block:: bash salt '*' openvswitch.port_remove br0 8080 """ param_if_exists = _param_if_exists(if_exists) if port and not br: cmd = "ovs-vsctl {1}del-port {0}".format(port, param_if_exists) else: cmd = "ovs-vsctl {2}del-port {0} {1}".format(br, port, param_if_exists) result = __salt__["cmd.run_all"](cmd) retcode = result["retcode"] return _retcode_to_bool(retcode) def port_list(br): """ Lists all of the ports within bridge. Args: br: A string - bridge name. Returns: List of bridges (or empty list), False on failure. .. versionadded:: 2016.3.0 CLI Example: .. code-block:: bash salt '*' openvswitch.port_list br0 """ cmd = "ovs-vsctl list-ports {}".format(br) result = __salt__["cmd.run_all"](cmd) retcode = result["retcode"] stdout = result["stdout"] return _stdout_list_split(retcode, stdout) def port_get_tag(port): """ Lists tags of the port. Args: port: A string - port name. Returns: List of tags (or empty list), False on failure. .. versionadded:: 2016.3.0 CLI Example: .. code-block:: bash salt '*' openvswitch.port_get_tag tap0 """ cmd = "ovs-vsctl get port {} tag".format(port) result = __salt__["cmd.run_all"](cmd) retcode = result["retcode"] stdout = result["stdout"] return _stdout_list_split(retcode, stdout) def interface_get_options(port): """ Port's interface's optional parameters. Args: port: A string - port name. Returns: String containing optional parameters of port's interface, False on failure. .. versionadded:: 2016.3.0 CLI Example: .. code-block:: bash salt '*' openvswitch.interface_get_options tap0 """ cmd = "ovs-vsctl get interface {} options".format(port) result = __salt__["cmd.run_all"](cmd) retcode = result["retcode"] stdout = result["stdout"] return _stdout_list_split(retcode, stdout) def interface_get_type(port): """ Type of port's interface. Args: port: A string - port name. Returns: String - type of interface or empty string, False on failure. .. versionadded:: 2016.3.0 CLI Example: .. code-block:: bash salt '*' openvswitch.interface_get_type tap0 """ cmd = "ovs-vsctl get interface {} type".format(port) result = __salt__["cmd.run_all"](cmd) retcode = result["retcode"] stdout = result["stdout"] return _stdout_list_split(retcode, stdout) def port_create_vlan(br, port, id, internal=False): """ Isolate VM traffic using VLANs. Args: br: A string - bridge name. port: A string - port name. id: An integer in the valid range 0 to 4095 (inclusive), name of VLAN. internal: A boolean to create an internal interface if one does not exist. Returns: True on success, else False. .. versionadded:: 2016.3.0 CLI Example: .. code-block:: bash salt '*' openvswitch.port_create_vlan br0 tap0 100 """ interfaces = __salt__["network.interfaces"]() if not 0 <= id <= 4095: return False elif not bridge_exists(br): return False elif not internal and port not in interfaces: return False elif port in port_list(br): cmd = "ovs-vsctl set port {} tag={}".format(port, id) if internal: cmd += " -- set interface {} type=internal".format(port) result = __salt__["cmd.run_all"](cmd) return _retcode_to_bool(result["retcode"]) else: cmd = "ovs-vsctl add-port {} {} tag={}".format(br, port, id) if internal: cmd += " -- set interface {} type=internal".format(port) result = __salt__["cmd.run_all"](cmd) return _retcode_to_bool(result["retcode"]) def port_create_gre(br, port, id, remote): """ Generic Routing Encapsulation - creates GRE tunnel between endpoints. Args: br: A string - bridge name. port: A string - port name. id: An integer - unsigned 32-bit number, tunnel's key. remote: A string - remote endpoint's IP address. Returns: True on success, else False. .. versionadded:: 2016.3.0 CLI Example: .. code-block:: bash salt '*' openvswitch.port_create_gre br0 gre1 5001 192.168.1.10 """ if not 0 <= id < 2 ** 32: return False elif not __salt__["dig.check_ip"](remote): return False elif not bridge_exists(br): return False elif port in port_list(br): cmd = "ovs-vsctl set interface {} type=gre options:remote_ip={} options:key={}".format( port, remote, id ) result = __salt__["cmd.run_all"](cmd) return _retcode_to_bool(result["retcode"]) else: cmd = ( "ovs-vsctl add-port {0} {1} -- set interface {1} type=gre" " options:remote_ip={2} options:key={3}".format(br, port, remote, id) ) result = __salt__["cmd.run_all"](cmd) return _retcode_to_bool(result["retcode"]) def port_create_vxlan(br, port, id, remote, dst_port=None): """ Virtual eXtensible Local Area Network - creates VXLAN tunnel between endpoints. Args: br: A string - bridge name. port: A string - port name. id: An integer - unsigned 64-bit number, tunnel's key. remote: A string - remote endpoint's IP address. dst_port: An integer - port to use when creating tunnelport in the switch. Returns: True on success, else False. .. versionadded:: 2016.3.0 CLI Example: .. code-block:: bash salt '*' openvswitch.port_create_vxlan br0 vx1 5001 192.168.1.10 8472 """ dst_port = " options:dst_port=" + str(dst_port) if 0 < dst_port <= 65535 else "" if not 0 <= id < 2 ** 64: return False elif not __salt__["dig.check_ip"](remote): return False elif not bridge_exists(br): return False elif port in port_list(br): cmd = ( "ovs-vsctl set interface {} type=vxlan options:remote_ip={} " "options:key={}{}".format(port, remote, id, dst_port) ) result = __salt__["cmd.run_all"](cmd) return _retcode_to_bool(result["retcode"]) else: cmd = ( "ovs-vsctl add-port {0} {1} -- set interface {1} type=vxlan" " options:remote_ip={2} options:key={3}{4}".format( br, port, remote, id, dst_port ) ) result = __salt__["cmd.run_all"](cmd) return _retcode_to_bool(result["retcode"])