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)
@classmethod
[docs] 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):
@classmethod
[docs] 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):
@classmethod
[docs] 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)
@staticmethod
[docs] 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
@classmethod
[docs] 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.
"""
@classmethod
[docs] 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.
"""
@classmethod
[docs] 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)