Source code for autotest.client.shared.openvswitch

import logging
import os
import re
import signal

try:
    import autotest.common as common  # pylint: disable=W0611
except ImportError:
    import common  # pylint: disable=W0611
from autotest.client import utils, os_dep
from autotest.client.shared import error
from autotest.client.shared.utils import VersionableClass


[docs]class ServiceManagerInterface(VersionableClass): def __new__(cls, *args, **kargs): ServiceManagerInterface.master_class = ServiceManagerInterface return super(ServiceManagerInterface, cls).__new__(cls, *args, **kargs)
[docs] @classmethod def get_version(cls): """ Get version of ServiceManager. :return: Version of ServiceManager. """ return open("/proc/1/comm", "r").read().strip()
[docs] def stop(self, service_name): raise NotImplementedError("Method 'stop' must be" " implemented in child class")
[docs] def start(self, service_name): raise NotImplementedError("Method 'start' must be" " implemented in child class")
[docs] def restart(self, service_name): raise NotImplementedError("Method 'restart' must be" " implemented in child class")
[docs] def status(self, service_name): raise NotImplementedError("Method 'status' must be" " implemented in child class")
[docs]class ServiceManagerSystemD(ServiceManagerInterface, VersionableClass):
[docs] @classmethod def is_right_version(cls, version): if version == "systemd": return True return False
[docs] def stop(self, service_name): utils.run("systemctl stop %s.service" % (service_name))
[docs] def start(self, service_name): utils.run("systemctl start %s.service" % (service_name))
[docs] def restart(self, service_name): utils.run("systemctl restart %s.service" % (service_name))
[docs] def status(self, service_name): utils.run("systemctl show %s.service" % (service_name))
[docs]class ServiceManagerSysvinit(ServiceManagerInterface, VersionableClass):
[docs] @classmethod def is_right_version(cls, version): if version == "init": return True return False
[docs] def stop(self, service_name): utils.run("/etc/init.d/%s stop" % (service_name))
[docs] def start(self, service_name): utils.run("/etc/init.d/%s start" % (service_name))
[docs] def restart(self, service_name): utils.run("/etc/init.d/%s restart" % (service_name))
[docs]class ServiceManager(ServiceManagerInterface): pass
[docs]class OpenVSwitchControl(object): """ Class select the best matches control class for installed version of OpenVSwitch. OpenVSwtich parameters are described in man ovs-vswitchd.conf.db """ def __new__(cls, db_path=None, db_socket=None, db_pidfile=None, ovs_pidfile=None, dbschema=None, install_prefix=None): """ Makes initialization of OpenVSwitch. :param tmpdir: Tmp directory for save openvswitch test files. :param db_path: Path of OVS databimpoty ase. :param db_socket: Path of OVS db socket. :param db_pidfile: Path of OVS db ovsdb-server pid. :param ovs_pidfile: Path of OVS ovs-vswitchd pid. :param install_prefix: Path where is openvswitch installed. """ # if path is None set default path. if not install_prefix: install_prefix = "/" if not db_path: db_path = os.path.join(install_prefix, "/etc/openvswitch/conf.db") if not db_socket: db_socket = os.path.join(install_prefix, "/var/run/openvswitch/db.sock") if not db_pidfile: db_pidfile = os.path.join(install_prefix, "/var/run/openvswitch/ovsdb-server.pid") if not ovs_pidfile: ovs_pidfile = os.path.join(install_prefix, "/var/run/openvswitch/ovs-vswitchd.pid") if not dbschema: dbschema = os.path.join(install_prefix, "/usr/share/openvswitch/vswitch.ovsschema") OpenVSwitchControl.install_prefix = install_prefix OpenVSwitchControl.db_path = db_path OpenVSwitchControl.db_socket = db_socket OpenVSwitchControl.db_pidfile = db_pidfile OpenVSwitchControl.ovs_pidfile = ovs_pidfile OpenVSwitchControl.dbschema = install_prefix, dbschema os.environ["PATH"] = (os.path.join(install_prefix, "usr/bin:") + os.environ["PATH"]) os.environ["PATH"] = (os.path.join(install_prefix, "usr/sbin:") + os.environ["PATH"]) return super(OpenVSwitchControl, cls).__new__(cls)
[docs] @staticmethod def convert_version_to_int(version): """ :param version: (int) Converted from version string 1.4.0 => int 140 """ if isinstance(version, int): return version try: a = re.findall('^(\d+)\.?(\d+)\.?(\d+)\-?', version)[0] int_ver = ''.join(a) except Exception: raise error.AutotestError("Wrong version format '%s'" % version) return int_ver
[docs] @classmethod def get_version(cls): """ Get version of installed OpenVSwtich. :return: Version of OpenVSwtich. """ version = None try: result = utils.run(os_dep.command("ovs-vswitchd"), args=["--version"]) pattern = "ovs-vswitchd \(Open vSwitch\) (.+)" version = re.search(pattern, result.stdout).group(1) except error.CmdError: logging.debug("OpenVSwitch is not available in system.") return version
[docs] def status(self): raise NotImplementedError()
[docs] def add_br(self, br_name): raise NotImplementedError()
[docs] def del_br(self, br_name): raise NotImplementedError()
[docs] def br_exist(self, br_name): raise NotImplementedError()
[docs] def list_br(self): raise NotImplementedError()
[docs] def add_port(self, br_name, port_name): raise NotImplementedError()
[docs] def del_port(self, br_name, port_name): raise NotImplementedError()
[docs] def add_port_tag(self, port_name, tag): raise NotImplementedError()
[docs] def add_port_trunk(self, port_name, trunk): raise NotImplementedError()
[docs] def set_vlanmode(self, port_name, vlan_mode): raise NotImplementedError()
[docs] def check_port_in_br(self, br_name, port_name): raise NotImplementedError()
[docs]class OpenVSwitchControlCli(OpenVSwitchControl, VersionableClass): """ Class select the best matches control class for installed version of OpenVSwitch. """ def __new__(cls, db_path=None, db_socket=None, db_pidfile=None, ovs_pidfile=None, dbschema=None, install_prefix=None): OpenVSwitchControlCli.master_class = OpenVSwitchControlCli return super(OpenVSwitchControlCli, cls).__new__(cls, db_path, db_socket, db_pidfile, ovs_pidfile, dbschema, install_prefix)
[docs]class OpenVSwitchControlDB(OpenVSwitchControl, VersionableClass): """ Class select the best matches control class for installed version of OpenVSwitch. """ def __new__(cls, db_path=None, db_socket=None, db_pidfile=None, ovs_pidfile=None, dbschema=None, install_prefix=None): OpenVSwitchControlDB.master_class = OpenVSwitchControlDB return super(OpenVSwitchControlDB, cls).__new__(cls, db_path, db_socket, db_pidfile, ovs_pidfile, dbschema, install_prefix)
[docs]class OpenVSwitchControlDB_140(OpenVSwitchControlDB, VersionableClass): """ Don't use this class directly. This class is automatically selected by OpenVSwitchControl. """
[docs] @classmethod def is_right_version(cls, version): """ Check condition for select control class. :param version: version of OpenVSwtich """ if version is not None: int_ver = cls.convert_version_to_int(version) if int_ver <= 140: return True return False
# TODO: implement database manipulation methods.
[docs]class OpenVSwitchControlCli_140(OpenVSwitchControlCli, VersionableClass): """ Don't use this class directly. This class is automatically selected by OpenVSwitchControl. """
[docs] @classmethod def is_right_version(cls, version): """ Check condition for select control class. :param version: version of OpenVSwtich """ if version is not None: int_ver = cls.convert_version_to_int(version) if int_ver <= 140: return True return False
[docs] def ovs_vsctl(self, parmas, ignore_status=False): return utils.run(os_dep.command("ovs-vsctl"), timeout=10, ignore_status=ignore_status, verbose=False, args=["--db=unix:%s" % (self.db_socket)] + parmas)
[docs] def status(self): return self.ovs_vsctl(["show"]).stdout
[docs] def add_br(self, br_name): self.ovs_vsctl(["add-br", br_name])
[docs] def add_fake_br(self, br_name, parent, vlan): self.ovs_vsctl(["add-br", br_name, parent, vlan])
[docs] def del_br(self, br_name): try: self.ovs_vsctl(["del-br", br_name]) except error.CmdError, e: logging.debug(e.result_obj) raise
[docs] def br_exist(self, br_name): try: self.ovs_vsctl(["br-exists", br_name]) except error.CmdError, e: if e.result_obj.exit_status == 2: return False else: raise return True
[docs] def list_br(self): return self.ovs_vsctl(["list-br"]).stdout.splitlines()
[docs] def add_port(self, br_name, port_name): self.ovs_vsctl(["add-port", br_name, port_name])
[docs] def del_port(self, br_name, port_name): self.ovs_vsctl(["del-port", br_name, port_name])
[docs] def add_port_tag(self, port_name, tag): self.ovs_vsctl(["set", "Port", port_name, "tag=%s" % tag])
[docs] def add_port_trunk(self, port_name, trunk): """ :param trunk: list of vlans id. """ trunk = map(lambda x: str(x), trunk) trunk = "[" + ",".join(trunk) + "]" self.ovs_vsctl(["set", "Port", port_name, "trunk=%s" % trunk])
[docs] def set_vlanmode(self, port_name, vlan_mode): self.ovs_vsctl(["set", "Port", port_name, "vlan-mode=%s" % vlan_mode])
[docs] def list_ports(self, br_name): return self.ovs_vsctl(["list-ports", br_name]).stdout.splitlines()
[docs] def port_to_br(self, port_name): """ Return bridge which contain port. :param port_name: Name of port. :return: Bridge name or None if there is no bridge which contain port. """ bridge = None try: bridge = self.ovs_vsctl(["port-to-br", port_name]).stdout except error.CmdError, e: if e.result_obj.exit_status == 1: pass return bridge
[docs]class OpenVSwitchSystem(OpenVSwitchControlCli, OpenVSwitchControlDB): """ OpenVSwtich class. """ def __new__(cls, db_path=None, db_socket=None, db_pidfile=None, ovs_pidfile=None, dbschema=None, install_prefix=None): return super(OpenVSwitchSystem, cls).__new__(cls, db_path, db_socket, db_pidfile, ovs_pidfile, dbschema, install_prefix) def __init__(self, db_path=None, db_socket=None, db_pidfile=None, ovs_pidfile=None, dbschema=None, install_prefix=None): """ Makes initialization of OpenVSwitch. :param db_path: Path of OVS database. :param db_socket: Path of OVS db socket. :param db_pidfile: Path of OVS db ovsdb-server pid. :param ovs_pidfile: Path of OVS ovs-vswitchd pid. :param install_prefix: Path where is openvswitch installed. """ super(OpenVSwitchSystem, self).__init__(self, db_path, db_socket, db_pidfile, ovs_pidfile, dbschema, install_prefix) self.cleanup = False self.pid_files_path = None
[docs] def is_installed(self): """ Check if OpenVSwitch is already installed in system on default places. :return: Version of OpenVSwtich. """ if self.get_version(): return True else: return False
[docs] def check_db_daemon(self): """ Check if OVS daemon is started correctly. """ working = utils.program_is_alive("ovsdb-server", self.pid_files_path) if not working: logging.error("OpenVSwitch database daemon with PID in file %s" " not working.", self.db_pidfile) return working
[docs] def check_switch_daemon(self): """ Check if OVS daemon is started correctly. """ working = utils.program_is_alive("ovs-vswitchd", self.pid_files_path) if not working: logging.error("OpenVSwitch switch daemon with PID in file %s" " not working.", self.ovs_pidfile) return working
[docs] def check_db_file(self): """ Check if db_file exists. """ exists = os.path.exists(self.db_path) if not exists: logging.error("OpenVSwitch database file %s not exists.", self.db_path) return exists
[docs] def check_db_socket(self): """ Check if db socket exists. """ exists = os.path.exists(self.db_socket) if not exists: logging.error("OpenVSwitch database socket file %s not exists.", self.db_socket) return exists
[docs] def check(self): return (self.check_db_daemon() and self.check_switch_daemon() and self.check_db_file() and self.check_db_socket())
[docs] def init_system(self): """ Create new dbfile without any configuration. """ sm = ServiceManager() try: if utils.load_module("openvswitch"): sm.restart("openvswitch") except error.CmdError: logging.error("Service OpenVSwitch is probably not" " installed in system.") raise self.pid_files_path = "/var/run/openvswitch/"
[docs] def clean(self): """ Empty cleanup function """ pass
[docs]class OpenVSwitch(OpenVSwitchSystem): """ OpenVSwtich class. """ def __new__(cls, tmpdir, db_path=None, db_socket=None, db_pidfile=None, ovs_pidfile=None, dbschema=None, install_prefix=None): return super(OpenVSwitch, cls).__new__(cls, db_path, db_socket, db_pidfile, ovs_pidfile, dbschema, install_prefix) def __init__(self, tmpdir, db_path=None, db_socket=None, db_pidfile=None, ovs_pidfile=None, dbschema=None, install_prefix=None): """ Makes initialization of OpenVSwitch. :param tmpdir: Tmp directory for save openvswitch test files. :param db_path: Path of OVS database. :param db_socket: Path of OVS db socket. :param db_pidfile: Path of OVS db ovsdb-server pid. :param ovs_pidfile: Path of OVS ovs-vswitchd pid. :param install_prefix: Path where is openvswitch installed. """ super(OpenVSwitch, self).__init__(db_path, db_socket, db_pidfile, ovs_pidfile, dbschema, install_prefix) self.tmpdir = "/%s/openvswitch" % (tmpdir) try: os.mkdir(self.tmpdir) except OSError, e: if e.errno != 17: raise
[docs] def init_db(self): utils.run(os_dep.command("ovsdb-tool"), timeout=10, args=["create", self.db_path, self.dbschema]) utils.run(os_dep.command("ovsdb-server"), timeout=10, args=["--remote=punix:%s" % (self.db_socket), "--remote=db:Open_vSwitch,manager_options", "--pidfile=%s" % (self.db_pidfile), "--detach"]) self.ovs_vsctl(["--no-wait", "init"])
[docs] def start_ovs_vswitchd(self): utils.run(os_dep.command("ovs-vswitchd"), timeout=10, args=["--detach", "--pidfile=%s" % (self.ovs_pidfile), "unix:%s" % (self.db_socket)])
[docs] def init_new(self): """ Create new dbfile without any configuration. """ self.db_path = os.path.join(self.tmpdir, "conf.db") self.db_socket = os.path.join(self.tmpdir, "db.sock") self.db_pidfile = utils.get_pid_path("ovsdb-server") self.ovs_pidfile = utils.get_pid_path("ovs-vswitchd") self.dbschema = "/usr/share/openvswitch/vswitch.ovsschema" self.cleanup = True sm = ServiceManager() # Stop system openvswitch try: sm.stop("openvswitch") except error.CmdError: pass utils.load_module("openvswitch") self.clean() if (os.path.exists(self.db_path)): os.remove(self.db_path) self.init_db() self.start_ovs_vswitchd()
[docs] def clean(self): logging.debug("Killall ovsdb-server") utils.signal_program("ovsdb-server") if (utils.program_is_alive("ovsdb-server")): utils.signal_program("ovsdb-server", signal.SIGKILL) logging.debug("Killall ovs-vswitchd") utils.signal_program("ovs-vswitchd") if (utils.program_is_alive("ovs-vswitchd")): utils.signal_program("ovs-vswitchd", signal.SIGKILL)