Revert "Rework venv to support arbitrary schemas"
Related-Bug: #2132018 This reverts commit9c1790796d. Revert "Improve Row stringification" This reverts commit7744650d02. Change-Id: I903334f4566ac6dd28452a21cde5ae96fd9a26e4 Signed-off-by: Rodolfo Alonso Hernandez <ralonsoh@redhat.com>
This commit is contained in:
@@ -14,7 +14,6 @@
|
||||
|
||||
import collections
|
||||
from collections import abc
|
||||
import functools
|
||||
# json is not deprecated
|
||||
# pylint: disable=deprecated-module
|
||||
import json
|
||||
@@ -25,7 +24,6 @@ import time
|
||||
import uuid
|
||||
|
||||
from ovs.db import idl
|
||||
from ovs.db import types
|
||||
from ovs import jsonrpc
|
||||
from ovs import poller
|
||||
from ovs import stream
|
||||
@@ -455,58 +453,15 @@ def db_replace_record(obj):
|
||||
return obj
|
||||
|
||||
|
||||
def process_value_for_str(row, col):
|
||||
class StrUuid(uuid.UUID):
|
||||
"""A UUID class that will return a repr of the UUID as the UUID string
|
||||
|
||||
This lets us use the default stringification of lists/dicts to display
|
||||
in the format we want without having to generate them ourselves
|
||||
"""
|
||||
__repr__ = uuid.UUID.__str__
|
||||
|
||||
@classmethod
|
||||
def from_col(cls, col_src, value):
|
||||
if col_src.is_ref():
|
||||
return cls(int=value.uuid.int)
|
||||
return cls(int=value.int)
|
||||
|
||||
# If we are passed UUID as a column, just return the modified row.uuid
|
||||
if col == 'uuid':
|
||||
return StrUuid(int=row.uuid.int)
|
||||
|
||||
val = getattr(row, col)
|
||||
col_type = row._table.columns[col].type
|
||||
if col_type.is_optional():
|
||||
try:
|
||||
val = val[0]
|
||||
except IndexError:
|
||||
return [] # Unset optional
|
||||
elif col_type.is_map():
|
||||
# pylint: disable=unnecessary-lambda-assignment
|
||||
_ = k = v = lambda x: x
|
||||
if col_type.key.type == types.UuidType:
|
||||
k = functools.partial(StrUuid.from_col, col_type.key)
|
||||
if col_type.value.type == types.UuidType:
|
||||
v = functools.partial(StrUuid.from_col, col_type.value)
|
||||
if k == v == _: # No change needed
|
||||
return val
|
||||
return {k(x): v(y) for x, y in val.items()}
|
||||
elif col_type.is_set():
|
||||
if col_type.key.type == types.UuidType:
|
||||
return [StrUuid.from_col(col_type.key, v) for v in val]
|
||||
return getattr(row, col)
|
||||
# optional and non-optional uuid-type columns
|
||||
if col_type.key.type == types.UuidType:
|
||||
return StrUuid.from_col(col_type.key, val)
|
||||
return val
|
||||
|
||||
|
||||
def row2str(row):
|
||||
return "{table}({data})".format(
|
||||
table=row._table.name,
|
||||
data=", ".join("{col!s}={val!r}".format(
|
||||
col=c, val=process_value_for_str(row, c))
|
||||
for c in ['uuid'] + sorted(row._table.columns) if hasattr(row, c)))
|
||||
"""Get a string representation of a Row"""
|
||||
|
||||
# This is not a repr, as the Row object takes a dict of Datum objects and
|
||||
# we don't really want to deal with those, just what the Python values are.
|
||||
# Row foreign keys are printed as their UUID
|
||||
return "%s(%s)" % (row._table.name, ", ".join(
|
||||
"%s=%s" % (col, idl._row_to_uuid(getattr(row, col)))
|
||||
for col in row._table.columns if hasattr(row, col)))
|
||||
|
||||
|
||||
def frozen_row(row):
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from ovsdbapp.backend.ovs_idl import idlutils
|
||||
|
||||
|
||||
class RowView(object):
|
||||
def __init__(self, row):
|
||||
@@ -29,6 +27,3 @@ class RowView(object):
|
||||
|
||||
def __hash__(self):
|
||||
return self._row.__hash__()
|
||||
|
||||
def __str__(self):
|
||||
return idlutils.row2str(self._row)
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
{
|
||||
"name": "idltest",
|
||||
"version": "1.0.0",
|
||||
"cksum": "123456789 1234",
|
||||
"tables": {
|
||||
"SimpleTypes": {
|
||||
"columns": {
|
||||
"integer_col": {"type": "integer"},
|
||||
"real_col": {"type": "real"},
|
||||
"boolean_col": {"type": "boolean"},
|
||||
"string_col": {"type": "string"},
|
||||
"uuid_col": {"type": "uuid"}
|
||||
},
|
||||
"isRoot": true
|
||||
},
|
||||
"OptionalTypes": {
|
||||
"columns": {
|
||||
"opt_integer": {"type": {"key": "integer", "min": 0, "max": 1}},
|
||||
"opt_real": {"type": {"key": "real", "min": 0, "max": 1}},
|
||||
"opt_boolean": {"type": {"key": "boolean", "min": 0, "max": 1}},
|
||||
"opt_string": {"type": {"key": "string", "min": 0, "max": 1}},
|
||||
"opt_uuid": {"type": {"key": "uuid", "min": 0, "max": 1}}
|
||||
},
|
||||
"isRoot": true
|
||||
},
|
||||
"SetTypes": {
|
||||
"columns": {
|
||||
"integer_set": {"type": {"key": "integer", "min": 0, "max": "unlimited"}},
|
||||
"real_set": {"type": {"key": "real", "min": 0, "max": "unlimited"}},
|
||||
"boolean_set": {"type": {"key": "boolean", "min": 0, "max": "unlimited"}},
|
||||
"string_set": {"type": {"key": "string", "min": 0, "max": "unlimited"}},
|
||||
"uuid_set": {"type": {"key": "uuid", "min": 0, "max": "unlimited"}}
|
||||
},
|
||||
"isRoot": true
|
||||
},
|
||||
"MapTypes": {
|
||||
"columns": {
|
||||
"int_int_map": {"type": {"key": "integer", "value": "integer", "min": 0, "max": "unlimited"}},
|
||||
"int_real_map": {"type": {"key": "integer", "value": "real", "min": 0, "max": "unlimited"}},
|
||||
"int_bool_map": {"type": {"key": "integer", "value": "boolean", "min": 0, "max": "unlimited"}},
|
||||
"int_string_map": {"type": {"key": "integer", "value": "string", "min": 0, "max": "unlimited"}},
|
||||
"int_uuid_map": {"type": {"key": "integer", "value": "uuid", "min": 0, "max": "unlimited"}},
|
||||
"real_int_map": {"type": {"key": "real", "value": "integer", "min": 0, "max": "unlimited"}},
|
||||
"real_real_map": {"type": {"key": "real", "value": "real", "min": 0, "max": "unlimited"}},
|
||||
"real_bool_map": {"type": {"key": "real", "value": "boolean", "min": 0, "max": "unlimited"}},
|
||||
"real_string_map": {"type": {"key": "real", "value": "string", "min": 0, "max": "unlimited"}},
|
||||
"real_uuid_map": {"type": {"key": "real", "value": "uuid", "min": 0, "max": "unlimited"}},
|
||||
"bool_int_map": {"type": {"key": "boolean", "value": "integer", "min": 0, "max": "unlimited"}},
|
||||
"bool_real_map": {"type": {"key": "boolean", "value": "real", "min": 0, "max": "unlimited"}},
|
||||
"bool_bool_map": {"type": {"key": "boolean", "value": "boolean", "min": 0, "max": "unlimited"}},
|
||||
"bool_string_map": {"type": {"key": "boolean", "value": "string", "min": 0, "max": "unlimited"}},
|
||||
"bool_uuid_map": {"type": {"key": "boolean", "value": "uuid", "min": 0, "max": "unlimited"}},
|
||||
"string_int_map": {"type": {"key": "string", "value": "integer", "min": 0, "max": "unlimited"}},
|
||||
"string_real_map": {"type": {"key": "string", "value": "real", "min": 0, "max": "unlimited"}},
|
||||
"string_bool_map": {"type": {"key": "string", "value": "boolean", "min": 0, "max": "unlimited"}},
|
||||
"string_string_map": {"type": {"key": "string", "value": "string", "min": 0, "max": "unlimited"}},
|
||||
"string_uuid_map": {"type": {"key": "string", "value": "uuid", "min": 0, "max": "unlimited"}},
|
||||
"uuid_int_map": {"type": {"key": "uuid", "value": "integer", "min": 0, "max": "unlimited"}},
|
||||
"uuid_real_map": {"type": {"key": "uuid", "value": "real", "min": 0, "max": "unlimited"}},
|
||||
"uuid_bool_map": {"type": {"key": "uuid", "value": "boolean", "min": 0, "max": "unlimited"}},
|
||||
"uuid_string_map": {"type": {"key": "uuid", "value": "string", "min": 0, "max": "unlimited"}},
|
||||
"uuid_uuid_map": {"type": {"key": "uuid", "value": "uuid", "min": 0, "max": "unlimited"}}
|
||||
},
|
||||
"isRoot": true
|
||||
},
|
||||
"RefTarget": {
|
||||
"columns": {
|
||||
"value": {"type": "integer"}
|
||||
},
|
||||
"isRoot": true
|
||||
},
|
||||
"RefTypes": {
|
||||
"columns": {
|
||||
"single_ref": {"type": {"key": {"type": "uuid", "refTable": "RefTarget"}}},
|
||||
"opt_ref": {"type": {"key": {"type": "uuid", "refTable": "RefTarget"}, "min": 0, "max": 1}},
|
||||
"ref_set": {"type": {"key": {"type": "uuid", "refTable": "RefTarget"}, "min": 0, "max": "unlimited"}},
|
||||
"ref_map_key": {"type": {"key": {"type": "uuid", "refTable": "RefTarget"}, "value": "string", "min": 0, "max": "unlimited"}},
|
||||
"ref_map_value": {"type": {"key": "string", "value": {"type": "uuid", "refTable": "RefTarget"}, "min": 0, "max": "unlimited"}},
|
||||
"ref_map_both": {"type": {"key": {"type": "uuid", "refTable": "RefTarget"}, "value": {"type": "uuid", "refTable": "RefTarget"}, "min": 0, "max": "unlimited"}}
|
||||
},
|
||||
"isRoot": true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,162 +0,0 @@
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import uuid
|
||||
|
||||
from ovsdbapp import api
|
||||
from ovsdbapp.backend import ovs_idl
|
||||
from ovsdbapp.backend.ovs_idl import connection
|
||||
from ovsdbapp import constants
|
||||
from ovsdbapp.tests.functional import base
|
||||
from ovsdbapp import venv
|
||||
|
||||
# flake8 wrongly reports line 1 in the license has an f-string with a single }
|
||||
# flake8: noqa E999
|
||||
|
||||
class IdlTestApi(ovs_idl.Backend, api.API):
|
||||
pass
|
||||
|
||||
|
||||
class IdlUtilsRow2StrTestCase(base.VenvPerClassFunctionalTestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
schema_path = os.path.join(
|
||||
os.path.dirname(__file__), 'idltest.ovsschema')
|
||||
cls.ovsdb_server = venv.OvsdbServerFixture(
|
||||
cls.virtualenv, "idltest", schema_path)
|
||||
cls.ovsdb_server.setUp()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.ovsdb_server.cleanUp()
|
||||
super().tearDownClass()
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.idl = connection.OvsdbIdl.from_server(
|
||||
self.ovsdb_server.connection, "idltest")
|
||||
self.connection = connection.Connection(self.idl,
|
||||
constants.DEFAULT_TIMEOUT)
|
||||
self.api = IdlTestApi(self.connection)
|
||||
|
||||
def test_simple_row(self):
|
||||
data = {
|
||||
"integer_col": 42,
|
||||
"real_col": 3.14159,
|
||||
"boolean_col": True,
|
||||
"string_col": "test_simple",
|
||||
"uuid_col": uuid.uuid4()}
|
||||
row = self.api.db_create_row("SimpleTypes",
|
||||
**data).execute(check_error=True)
|
||||
self.assertEqual(f"SimpleTypes(uuid={row.uuid}, "
|
||||
f"boolean_col={data['boolean_col']}, "
|
||||
f"integer_col={data['integer_col']}, "
|
||||
f"real_col={data['real_col']}, "
|
||||
f"string_col='{data['string_col']}', "
|
||||
f"uuid_col={data['uuid_col']})",
|
||||
str(row))
|
||||
|
||||
def test_optional_row_unset(self):
|
||||
row = self.api.db_create_row("OptionalTypes").execute(check_error=True)
|
||||
self.assertEqual(f"OptionalTypes(uuid={row.uuid}, opt_boolean=[], "
|
||||
"opt_integer=[], opt_real=[], opt_string=[], "
|
||||
"opt_uuid=[])", str(row))
|
||||
|
||||
def test_option_row_set(self):
|
||||
data = {
|
||||
"opt_integer": 42,
|
||||
"opt_real": 3.14159,
|
||||
"opt_boolean": False,
|
||||
"opt_string": "foo",
|
||||
"opt_uuid": uuid.uuid4()}
|
||||
row = self.api.db_create_row("OptionalTypes", **data).execute(
|
||||
check_error=True)
|
||||
self.assertEqual(f"OptionalTypes(uuid={row.uuid}, "
|
||||
f"opt_boolean={data['opt_boolean']}, "
|
||||
f"opt_integer={data['opt_integer']}, "
|
||||
f"opt_real={data['opt_real']}, "
|
||||
f"opt_string='{data['opt_string']}', "
|
||||
f"opt_uuid={data['opt_uuid']})", str(row))
|
||||
|
||||
def test_set_types(self):
|
||||
data = {
|
||||
"integer_set": [1, 2, 3],
|
||||
"real_set": [1.1, 2.2, 3.3],
|
||||
"boolean_set": [True, False],
|
||||
"string_set": ["foo", "bar"],
|
||||
"uuid_set": [uuid.uuid4(), uuid.uuid4()]}
|
||||
string_set_str = ", ".join(repr(d) for d in sorted(data['string_set']))
|
||||
uuid_set_str = ", ".join(str(d) for d in sorted(data['uuid_set']))
|
||||
row = self.api.db_create_row("SetTypes", **data).execute()
|
||||
self.assertEqual(f"SetTypes(uuid={row.uuid}, "
|
||||
f"boolean_set={sorted(data['boolean_set'])}, "
|
||||
f"integer_set={sorted(data['integer_set'])}, "
|
||||
f"real_set={sorted(data['real_set'])}, "
|
||||
f"string_set=[{string_set_str}], "
|
||||
f"uuid_set=[{uuid_set_str}])", str(row))
|
||||
|
||||
def test_map_types(self):
|
||||
import itertools
|
||||
vals = {"int": 42, "real": 3.14, "bool": False,
|
||||
"string": "foo", "uuid": uuid.uuid4()}
|
||||
data = {f"{a}_{b}_map": {vals[a]: vals[b]}
|
||||
for a, b in itertools.product(vals.keys(), vals.keys())}
|
||||
row = self.api.db_create_row("MapTypes", **data).execute()
|
||||
self.assertEqual(
|
||||
f"MapTypes(uuid={row.uuid}, "
|
||||
f"bool_bool_map={{{vals['bool']}: {vals['bool']}}}, "
|
||||
f"bool_int_map={{{vals['bool']}: {vals['int']}}}, "
|
||||
f"bool_real_map={{{vals['bool']}: {vals['real']}}}, "
|
||||
f"bool_string_map={{{vals['bool']}: '{vals['string']}'}}, "
|
||||
f"bool_uuid_map={{{vals['bool']}: {vals['uuid']}}}, "
|
||||
f"int_bool_map={{{vals['int']}: {vals['bool']}}}, "
|
||||
f"int_int_map={{{vals['int']}: {vals['int']}}}, "
|
||||
f"int_real_map={{{vals['int']}: {vals['real']}}}, "
|
||||
f"int_string_map={{{vals['int']}: '{vals['string']}'}}, "
|
||||
f"int_uuid_map={{{vals['int']}: {vals['uuid']}}}, "
|
||||
f"real_bool_map={{{vals['real']}: {vals['bool']}}}, "
|
||||
f"real_int_map={{{vals['real']}: {vals['int']}}}, "
|
||||
f"real_real_map={{{vals['real']}: {vals['real']}}}, "
|
||||
f"real_string_map={{{vals['real']}: '{vals['string']}'}}, "
|
||||
f"real_uuid_map={{{vals['real']}: {vals['uuid']}}}, "
|
||||
f"string_bool_map={{'{vals['string']}': {vals['bool']}}}, "
|
||||
f"string_int_map={{'{vals['string']}': {vals['int']}}}, "
|
||||
f"string_real_map={{'{vals['string']}': {vals['real']}}}, "
|
||||
f"string_string_map={{'{vals['string']}': '{vals['string']}'}}, "
|
||||
f"string_uuid_map={{'{vals['string']}': {vals['uuid']}}}, "
|
||||
f"uuid_bool_map={{{vals['uuid']}: {vals['bool']}}}, "
|
||||
f"uuid_int_map={{{vals['uuid']}: {vals['int']}}}, "
|
||||
f"uuid_real_map={{{vals['uuid']}: {vals['real']}}}, "
|
||||
f"uuid_string_map={{{vals['uuid']}: '{vals['string']}'}}, "
|
||||
f"uuid_uuid_map={{{vals['uuid']}: {vals['uuid']}}})", str(row))
|
||||
|
||||
def test_ref_types(self):
|
||||
ref_target = self.api.db_create_row("RefTarget", value=42).execute()
|
||||
ref_target = ref_target.uuid
|
||||
data = {
|
||||
"single_ref": ref_target,
|
||||
"ref_set": [ref_target],
|
||||
"ref_map_key": {ref_target: "foo"},
|
||||
"ref_map_value": {"foo": ref_target},
|
||||
"ref_map_both": {ref_target: ref_target}}
|
||||
row = self.api.db_create_row("RefTypes", **data).execute()
|
||||
self.assertEqual(
|
||||
f"RefTypes(uuid={row.uuid}, "
|
||||
"opt_ref=[], "
|
||||
f"ref_map_both={{{ref_target}: {ref_target}}}, "
|
||||
f"ref_map_key={{{ref_target}: 'foo'}}, "
|
||||
f"ref_map_value={{'foo': {ref_target}}}, "
|
||||
f"ref_set=[{ref_target}], "
|
||||
f"single_ref={ref_target})", str(row))
|
||||
@@ -10,7 +10,9 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import atexit
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from ovsdbapp.backend.ovs_idl import connection
|
||||
from ovsdbapp import constants
|
||||
@@ -18,39 +20,7 @@ from ovsdbapp.tests import base
|
||||
from ovsdbapp import venv
|
||||
|
||||
|
||||
class VenvPerClassFunctionalTestCase(base.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.virtualenv = venv.VenvFixture(
|
||||
remove=not bool(os.getenv("KEEP_VENV")))
|
||||
cls.virtualenv.setUp()
|
||||
cls.ovsvenvlog = None
|
||||
if os.getenv('KEEP_VENV') and os.getenv('VIRTUAL_ENV'):
|
||||
cls.ovsvenvlog = open(
|
||||
os.path.join(os.getenv('VIRTUAL_ENV'),
|
||||
'ovsvenv.%s' % os.getpid()), 'a+')
|
||||
cls.ovsvenvlog.write("%s\n" % cls.ovsvenv.venv)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
if cls.ovsvenvlog:
|
||||
cls.ovsvenvlog.close()
|
||||
cls.virtualenv.cleanUp()
|
||||
super().tearDownClass()
|
||||
|
||||
@classmethod
|
||||
def venv_log(cls, val):
|
||||
if cls.ovsvenvlog:
|
||||
cls.ovsvenvlog.write("%s\n" % val)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.venv_log(self.id())
|
||||
|
||||
|
||||
class FunctionalTestCase(VenvPerClassFunctionalTestCase):
|
||||
class FunctionalTestCase(base.TestCase):
|
||||
_connections = None
|
||||
fixture_class = venv.OvsOvnVenvFixture
|
||||
|
||||
@@ -58,19 +28,28 @@ class FunctionalTestCase(VenvPerClassFunctionalTestCase):
|
||||
def setUpClass(cls):
|
||||
super().setUpClass()
|
||||
cls.ovsvenv = cls.fixture_class(
|
||||
cls.virtualenv,
|
||||
tempfile.mkdtemp(),
|
||||
ovsdir=os.getenv('OVS_SRCDIR'),
|
||||
ovndir=os.getenv('OVN_SRCDIR'))
|
||||
ovndir=os.getenv('OVN_SRCDIR'),
|
||||
remove=not bool(os.getenv('KEEP_VENV')))
|
||||
atexit.register(cls.ovsvenv.cleanUp)
|
||||
cls.ovsvenv.setUp()
|
||||
cls.schema_map = {'Open_vSwitch': cls.ovsvenv.ovs_connection,
|
||||
'OVN_Northbound': cls.ovsvenv.ovnnb_connection,
|
||||
'OVN_Southbound': cls.ovsvenv.ovnsb_connection,
|
||||
}
|
||||
cls.ovsvenvlog = None
|
||||
if os.getenv('KEEP_VENV') and os.getenv('VIRTUAL_ENV'):
|
||||
cls.ovsvenvlog = open(
|
||||
os.path.join(os.getenv('VIRTUAL_ENV'),
|
||||
'ovsvenv.%s' % os.getpid()), 'a+')
|
||||
atexit.register(cls.ovsvenvlog.close)
|
||||
cls.ovsvenvlog.write("%s\n" % cls.ovsvenv.venv)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls.ovsvenv.cleanUp()
|
||||
super().tearDownClass()
|
||||
def venv_log(cls, val):
|
||||
if cls.ovsvenvlog:
|
||||
cls.ovsvenvlog.write("%s\n" % val)
|
||||
|
||||
@property
|
||||
def connection(self):
|
||||
@@ -92,5 +71,6 @@ class FunctionalTestCase(VenvPerClassFunctionalTestCase):
|
||||
return connection.Connection(idl, constants.DEFAULT_TIMEOUT)
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
super(FunctionalTestCase, self).setUp()
|
||||
self.venv_log(self.id())
|
||||
self.set_connection()
|
||||
|
||||
553
ovsdbapp/venv.py
553
ovsdbapp/venv.py
@@ -10,13 +10,12 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import errno
|
||||
import json
|
||||
import glob
|
||||
import os
|
||||
import shutil
|
||||
import signal
|
||||
import subprocess
|
||||
import tempfile
|
||||
import time
|
||||
|
||||
import fixtures
|
||||
|
||||
@@ -27,324 +26,126 @@ DUMMY_OVERRIDE_SYSTEM = 'system'
|
||||
DUMMY_OVERRIDE_NONE = ''
|
||||
|
||||
|
||||
def get_pid(filename):
|
||||
with open(filename) as f:
|
||||
return int(f.read().strip())
|
||||
|
||||
|
||||
def kill_pid(pidfile):
|
||||
"""Kill process using PID from pidfile, handling common exceptions."""
|
||||
try:
|
||||
os.kill(get_pid(pidfile), signal.SIGTERM)
|
||||
except (FileNotFoundError, ProcessLookupError):
|
||||
pass # Process already stopped or pidfile doesn't exist
|
||||
|
||||
|
||||
class VenvFixture(fixtures.Fixture):
|
||||
|
||||
def __init__(self, venvdir=None, remove=False):
|
||||
super().__init__()
|
||||
self.venvdir = venvdir or tempfile.mkdtemp()
|
||||
self.env = {
|
||||
"OVS_RUNDIR": self.venvdir,
|
||||
"OVS_LOGDIR": self.venvdir,
|
||||
"OVS_DBDIR": self.venvdir,
|
||||
"OVS_SYSCONFDIR": self.venvdir,
|
||||
"PATH": ""}
|
||||
self.remove = remove
|
||||
|
||||
def deactivate(self):
|
||||
if self.remove:
|
||||
shutil.rmtree(self.venvdir, ignore_errors=True)
|
||||
|
||||
def _setUp(self):
|
||||
super()._setUp()
|
||||
self.addCleanup(self.deactivate)
|
||||
|
||||
def call(self, cmd, *args, **kwargs):
|
||||
cwd = kwargs.pop("cwd", self.venvdir)
|
||||
try:
|
||||
return subprocess.check_output(
|
||||
cmd, *args, env=self.env, stderr=subprocess.STDOUT,
|
||||
cwd=cwd, **kwargs)
|
||||
except subprocess.CalledProcessError as e:
|
||||
raise Exception(
|
||||
f"Command {cmd} failed with error: {e.returncode} {e.output}")
|
||||
|
||||
def set_path(self, path):
|
||||
self.env["PATH"] = path
|
||||
|
||||
def prepend_paths(self, *dirs):
|
||||
self.env["PATH"] = os.pathsep.join((os.pathsep.join(dirs),
|
||||
self.env["PATH"]))
|
||||
|
||||
@classmethod
|
||||
def from_fixtures(cls, fixtures, *args, **kwargs):
|
||||
"""Create a VenvFixture with an environment from a list of fixtures."""
|
||||
venv = cls(*args, **kwargs)
|
||||
for fixture in fixtures:
|
||||
# use dict.fromkeys to deduplicate paths while maintaining order
|
||||
existing_path = dict.fromkeys(
|
||||
fixture.env["PATH"].split(os.pathsep))
|
||||
new_path = dict.fromkeys(fixture.env["PATH"].split(os.pathsep))
|
||||
new_path.update(existing_path)
|
||||
venv.env.update(fixture.env)
|
||||
venv.env["PATH"] = os.pathsep.join(new_path)
|
||||
return venv
|
||||
|
||||
|
||||
class OvsdbServerFixture(fixtures.Fixture):
|
||||
def __init__(self, venv, name, schema_filename, ovsdir=None, *args):
|
||||
super().__init__()
|
||||
self.venv = venv
|
||||
self.name = name
|
||||
self.schema_filename = schema_filename
|
||||
self.ovsdir = ovsdir
|
||||
self.args = args
|
||||
self.additional_dbs = []
|
||||
self.schema = self.get_schema_name()
|
||||
if not self.ovsdir:
|
||||
self.venv.set_path(os.getenv("PATH"))
|
||||
elif not os.path.isdir(self.ovsdir):
|
||||
raise FileNotFoundError(
|
||||
errno.ENOENT, "OVS source directory not found", self.ovsdir)
|
||||
else:
|
||||
self.venv.prepend_paths(os.path.join(self.ovsdir, "ovsdb"),
|
||||
os.path.join(self.ovsdir, "utilities"))
|
||||
|
||||
def get_schema_name(self):
|
||||
with open(self.schema_filename) as f:
|
||||
return json.load(f)["name"]
|
||||
|
||||
@property
|
||||
def unix_socket(self):
|
||||
return os.path.join(self.venv.venvdir, f"{self.name}.sock")
|
||||
|
||||
@property
|
||||
def pidfile(self):
|
||||
return os.path.join(self.venv.venvdir, f"{self.name}.pid")
|
||||
|
||||
@property
|
||||
def logfile(self):
|
||||
return os.path.join(self.venv.venvdir, f"{self.name}.log")
|
||||
|
||||
@property
|
||||
def dbfile(self):
|
||||
return os.path.join(self.venv.venvdir, f"{self.name}.db")
|
||||
|
||||
@property
|
||||
def connection(self):
|
||||
return "unix:" + self.unix_socket
|
||||
|
||||
def deactivate(self):
|
||||
kill_pid(self.pidfile)
|
||||
|
||||
def create_db(self, dbfile=None, schema_filename=None):
|
||||
dbfile = dbfile or self.dbfile
|
||||
schema_filename = schema_filename or self.schema_filename
|
||||
if os.path.isfile(dbfile):
|
||||
return
|
||||
self.venv.call(["ovsdb-tool", "-v", "create", dbfile, schema_filename])
|
||||
|
||||
def start(self):
|
||||
base_args = (
|
||||
"ovsdb-server",
|
||||
"--detach",
|
||||
"--no-chdir",
|
||||
"-vconsole:off",
|
||||
f"--pidfile={self.pidfile}",
|
||||
f"--log-file={self.logfile}",
|
||||
f"--remote=p{self.connection}")
|
||||
# TODO(twilson) Make SSL configurable since not all schemas
|
||||
# will support it the same way, e.g. OVN supports this but OVS doesn't
|
||||
# f"--private-key=db:{self.schema},SSL,private_key",
|
||||
# f"--certificate=db:{self.schema},SSL,certificate",
|
||||
# f"--ca-cert=db:{self.schema},SSL,ca_cert")
|
||||
|
||||
dbs = (self.dbfile,) + tuple(self.additional_dbs)
|
||||
self.venv.call(base_args + self.args + dbs)
|
||||
|
||||
def _setUp(self):
|
||||
super()._setUp()
|
||||
self.addCleanup(self.deactivate)
|
||||
self.create_db()
|
||||
self.start()
|
||||
|
||||
|
||||
class VswitchdFixture(fixtures.Fixture):
|
||||
def __init__(self, venv, ovsdb_server, dummy=DUMMY_OVERRIDE_ALL):
|
||||
super().__init__()
|
||||
self.venv = venv
|
||||
self.ovsdb_server = ovsdb_server
|
||||
self.dummy = dummy
|
||||
|
||||
@property
|
||||
def pidfile(self):
|
||||
return os.path.join(self.venv.venvdir, "ovs-vswitchd.pid")
|
||||
|
||||
@property
|
||||
def logfile(self):
|
||||
return os.path.join(self.venv.venvdir, "ovs-vswitchd.log")
|
||||
|
||||
@property
|
||||
def dummy_arg(self):
|
||||
return "--enable-dummy=%s" % self.dummy
|
||||
|
||||
def deactivate(self):
|
||||
kill_pid(self.pidfile)
|
||||
|
||||
def start(self):
|
||||
self.venv.call(
|
||||
["ovs-vswitchd",
|
||||
"--detach",
|
||||
"--no-chdir",
|
||||
f"--pidfile={self.pidfile}",
|
||||
"-vconsole:off",
|
||||
"-vvconn",
|
||||
"-vnetdev_dummy",
|
||||
f"--log-file={self.logfile}",
|
||||
self.dummy_arg,
|
||||
self.ovsdb_server.connection])
|
||||
|
||||
def _setUp(self):
|
||||
super()._setUp()
|
||||
self.addCleanup(self.deactivate)
|
||||
self.start()
|
||||
|
||||
|
||||
class NorthdFixture(fixtures.Fixture):
|
||||
def __init__(self, venv, ovnnb_connection, ovnsb_connection):
|
||||
super().__init__()
|
||||
self.venv = venv
|
||||
self.ovnnb_connection = ovnnb_connection
|
||||
self.ovnsb_connection = ovnsb_connection
|
||||
|
||||
@property
|
||||
def pidfile(self):
|
||||
return os.path.join(self.venv.venvdir, "ovn-northd.pid")
|
||||
|
||||
@property
|
||||
def logfile(self):
|
||||
return os.path.join(self.venv.venvdir, "ovn-northd.log")
|
||||
|
||||
def deactivate(self):
|
||||
kill_pid(self.pidfile)
|
||||
|
||||
def start(self):
|
||||
self.venv.call([
|
||||
"ovn-northd",
|
||||
"--detach",
|
||||
"--no-chdir",
|
||||
f"--pidfile={self.pidfile}",
|
||||
"-vconsole:off",
|
||||
f"--log-file={self.logfile}",
|
||||
f"--ovnsb-db={self.ovnsb_connection}",
|
||||
f"--ovnnb-db={self.ovnnb_connection}"])
|
||||
|
||||
def _setUp(self):
|
||||
super()._setUp()
|
||||
self.addCleanup(self.deactivate)
|
||||
self.start()
|
||||
|
||||
|
||||
class OvnControllerFixture(fixtures.Fixture):
|
||||
def __init__(self, venv):
|
||||
super().__init__()
|
||||
self.venv = venv
|
||||
|
||||
@property
|
||||
def pidfile(self):
|
||||
return os.path.join(self.venv.venvdir, "ovn-controller.pid")
|
||||
|
||||
@property
|
||||
def logfile(self):
|
||||
return os.path.join(self.venv.venvdir, "ovn-controller.log")
|
||||
|
||||
def deactivate(self):
|
||||
kill_pid(self.pidfile)
|
||||
|
||||
def start(self):
|
||||
self.venv.call([
|
||||
"ovn-controller",
|
||||
"--detach",
|
||||
"--no-chdir",
|
||||
f"--pidfile={self.pidfile}",
|
||||
"-vconsole:off",
|
||||
f"--log-file={self.logfile}"])
|
||||
|
||||
def _setUp(self):
|
||||
super()._setUp()
|
||||
self.addCleanup(self.deactivate)
|
||||
self.start()
|
||||
|
||||
|
||||
class OvsVenvFixture(fixtures.Fixture):
|
||||
PATH_VAR_TEMPLATE = "{0}/ovsdb:{0}/vswitchd:{0}/utilities"
|
||||
OVS_PATHS = (
|
||||
os.path.join(os.path.sep, 'usr', 'local', 'share', 'openvswitch'),
|
||||
os.path.join(os.path.sep, 'usr', 'share', 'openvswitch'))
|
||||
|
||||
OVS_SCHEMA = 'vswitch.ovsschema'
|
||||
|
||||
def __init__(self, venv=None, ovsdir=None, dummy=DUMMY_OVERRIDE_ALL):
|
||||
def __init__(self, venv, ovsdir=None, dummy=DUMMY_OVERRIDE_ALL,
|
||||
remove=False):
|
||||
"""Initialize fixture
|
||||
|
||||
:param venv: A VenvFixture
|
||||
:param venv: Path to venv directory.
|
||||
:param ovsdir: Path to directory containing ovs source codes.
|
||||
:param dummy: One of following: an empty string, 'override' or
|
||||
'system'.
|
||||
:param remove: Boolean value whether venv directory should be removed
|
||||
at the fixture cleanup.
|
||||
"""
|
||||
super().__init__()
|
||||
self.venv = venv or self.useFixture(VenvFixture())
|
||||
self.ovsdir = ovsdir or ()
|
||||
self.dummy = dummy
|
||||
self.venv = venv
|
||||
self.env = {'OVS_RUNDIR': self.venv, 'OVS_LOGDIR': self.venv,
|
||||
'OVS_DBDIR': self.venv, 'OVS_SYSCONFDIR': self.venv}
|
||||
if ovsdir and os.path.isdir(ovsdir):
|
||||
# From source directory
|
||||
self.venv.prepend_paths(os.path.join(ovsdir, "utilities"))
|
||||
self.venv.prepend_paths(os.path.join(ovsdir, "vswitchd"))
|
||||
# NOTE(twilson): We don't use useFixture here because we need to
|
||||
# separate the setUp/start and the initialization of the fixture so
|
||||
# that we can add additional DBs to the ovsdb-server fixture.
|
||||
self.ovsdb_server = OvsdbServerFixture(
|
||||
self.venv, "db", self.ovs_schema, self.ovsdir)
|
||||
self.env['PATH'] = (self.PATH_VAR_TEMPLATE.format(ovsdir) +
|
||||
":%s" % os.getenv('PATH'))
|
||||
else:
|
||||
# Use installed OVS
|
||||
self.env['PATH'] = os.getenv('PATH')
|
||||
|
||||
self.ovsdir = self._share_path(self.OVS_PATHS, ovsdir)
|
||||
self._dummy = dummy
|
||||
self.remove = remove
|
||||
self.ovsdb_server_dbs = []
|
||||
|
||||
@staticmethod
|
||||
def schema_path(search_paths, filename):
|
||||
paths = (os.path.join(p, filename) for p in search_paths)
|
||||
try:
|
||||
return next(p for p in paths if os.path.isfile(p))
|
||||
except StopIteration:
|
||||
raise FileNotFoundError(
|
||||
errno.ENOENT,
|
||||
f"Schema file {filename} not found in {search_paths}",
|
||||
filename)
|
||||
def _share_path(paths, override=None, files=tuple()):
|
||||
if not override:
|
||||
try:
|
||||
return next(
|
||||
p for p in paths if os.path.isdir(p) and
|
||||
all(os.path.isfile(os.path.join(p, f)) for f in files))
|
||||
except StopIteration:
|
||||
pass
|
||||
elif os.path.isdir(override):
|
||||
return override
|
||||
|
||||
@property
|
||||
def ovs_connection(self):
|
||||
return self.ovsdb_server.connection
|
||||
raise Exception("Invalid directories: %s" %
|
||||
", ".join(paths + (str(override),)))
|
||||
|
||||
@property
|
||||
def ovs_schema(self):
|
||||
return self.schema_path((self.ovsdir,) + self.OVS_PATHS,
|
||||
self.OVS_SCHEMA)
|
||||
path = os.path.join(self.ovsdir, 'vswitchd', self.OVS_SCHEMA)
|
||||
if os.path.isfile(path):
|
||||
return path
|
||||
return os.path.join(self.ovsdir, self.OVS_SCHEMA)
|
||||
|
||||
def call(self, *args, **kwargs):
|
||||
# For backwards compatibility
|
||||
return self.venv.call(*args, **kwargs)
|
||||
@property
|
||||
def dummy_arg(self):
|
||||
return "--enable-dummy=%s" % self._dummy
|
||||
|
||||
@property
|
||||
def ovs_connection(self):
|
||||
return 'unix:' + os.path.join(self.venv, 'db.sock')
|
||||
|
||||
def _setUp(self):
|
||||
super()._setUp()
|
||||
self.useFixture(self.ovsdb_server)
|
||||
self.vswitchd = self.useFixture(VswitchdFixture(
|
||||
self.venv, self.ovsdb_server, self.dummy))
|
||||
self.addCleanup(self.deactivate)
|
||||
if not os.path.isdir(self.venv):
|
||||
os.mkdir(self.venv)
|
||||
self.setup_dbs()
|
||||
self.start_ovsdb_processes()
|
||||
time.sleep(1) # wait_until_true(os.path.isfile(db_sock)
|
||||
self.init_processes()
|
||||
|
||||
def setup_dbs(self):
|
||||
db_filename = 'conf.db'
|
||||
self.create_db(db_filename, self.ovs_schema)
|
||||
self.ovsdb_server_dbs.append(db_filename)
|
||||
|
||||
def start_ovsdb_processes(self):
|
||||
self.call([
|
||||
'ovsdb-server',
|
||||
'--remote=p' + self.ovs_connection,
|
||||
'--detach', '--no-chdir', '--pidfile', '-vconsole:off',
|
||||
'--log-file'] + self.ovsdb_server_dbs)
|
||||
|
||||
def init_processes(self):
|
||||
self.venv.call([
|
||||
"ovs-vsctl",
|
||||
"--no-wait",
|
||||
f"--db={self.ovsdb_server.connection}",
|
||||
"--",
|
||||
"init"])
|
||||
self.call(['ovs-vsctl', '--no-wait', '--', 'init'])
|
||||
self.call(['ovs-vswitchd', '--detach', '--no-chdir', '--pidfile',
|
||||
'-vconsole:off', '-vvconn', '-vnetdev_dummy', '--log-file',
|
||||
self.dummy_arg, self.ovs_connection])
|
||||
|
||||
def deactivate(self):
|
||||
self.kill_processes()
|
||||
if self.remove:
|
||||
shutil.rmtree(self.venv, ignore_errors=True)
|
||||
|
||||
def create_db(self, name, schema):
|
||||
filename = os.path.join(self.venv, name)
|
||||
if not os.path.isfile(filename):
|
||||
return self.call(['ovsdb-tool', '-v', 'create', name, schema])
|
||||
|
||||
def call(self, cmd, *args, **kwargs):
|
||||
cwd = kwargs.pop('cwd', self.venv)
|
||||
return subprocess.check_call(
|
||||
cmd, *args, env=self.env, stderr=subprocess.STDOUT,
|
||||
cwd=cwd, **kwargs)
|
||||
|
||||
def get_pids(self):
|
||||
files = glob.glob(os.path.join(self.venv, "*.pid"))
|
||||
result = []
|
||||
for fname in files:
|
||||
with open(fname, 'r') as f:
|
||||
result.append(int(f.read().strip()))
|
||||
return result
|
||||
|
||||
def kill_processes(self):
|
||||
for pid in self.get_pids():
|
||||
os.kill(pid, signal.SIGTERM)
|
||||
|
||||
|
||||
class OvsOvnVenvFixture(OvsVenvFixture):
|
||||
@@ -358,117 +159,136 @@ class OvsOvnVenvFixture(OvsVenvFixture):
|
||||
IC_NBSCHEMA = 'ovn-ic-nb.ovsschema'
|
||||
|
||||
def __init__(self, venv, ovndir=None, add_chassis=False, **kwargs):
|
||||
super().__init__(venv, **kwargs)
|
||||
self.add_chassis = add_chassis
|
||||
self.ovndir = ovndir or ()
|
||||
if ovndir and os.path.isdir(ovndir):
|
||||
# Use OVN source dir
|
||||
self.PATH_VAR_TEMPLATE += (
|
||||
":{0}/controller:{0}/northd:{0}/utilities".format(ovndir))
|
||||
super().__init__(venv, **kwargs)
|
||||
self.ovndir = self._share_path(self.OVN_PATHS, ovndir,
|
||||
[self.SBSCHEMA, self.NBSCHEMA])
|
||||
self.env.update({'OVN_RUNDIR': self.venv})
|
||||
|
||||
@property
|
||||
def ovnsb_schema(self):
|
||||
search_paths = (self.ovndir,) + self.OVN_PATHS
|
||||
return self.schema_path(search_paths, self.SBSCHEMA)
|
||||
return os.path.join(self.ovndir, self.SBSCHEMA)
|
||||
|
||||
@property
|
||||
def ovnnb_schema(self):
|
||||
search_paths = (self.ovndir,) + self.OVN_PATHS
|
||||
return self.schema_path(search_paths, self.NBSCHEMA)
|
||||
return os.path.join(self.ovndir, self.NBSCHEMA)
|
||||
|
||||
@property
|
||||
def ovnnb_connection(self):
|
||||
return self.ovnnb_server.connection
|
||||
return 'unix:' + os.path.join(self.venv, 'ovnnb_db.sock')
|
||||
|
||||
@property
|
||||
def ovnsb_connection(self):
|
||||
return self.ovnsb_server.connection
|
||||
return 'unix:' + os.path.join(self.venv, 'ovnsb_db.sock')
|
||||
|
||||
def _setUp(self):
|
||||
if self.ovndir and os.path.isdir(self.ovndir):
|
||||
# Use OVN source dir - add paths to venv
|
||||
self.venv.prepend_paths(
|
||||
os.path.join(self.ovndir, "controller"),
|
||||
os.path.join(self.ovndir, "northd"),
|
||||
os.path.join(self.ovndir, "utilities"))
|
||||
self.venv.env.update({"OVN_RUNDIR": self.venv.venvdir})
|
||||
def setup_dbs(self):
|
||||
super().setup_dbs()
|
||||
self.create_db('ovnsb.db', self.ovnsb_schema)
|
||||
self.create_db('ovnnb.db', self.ovnnb_schema)
|
||||
|
||||
self.ovnnb_server = self.useFixture(OvsdbServerFixture(
|
||||
self.venv, "ovnnb_db", self.ovnnb_schema, self.ovsdir,
|
||||
"--remote=db:OVN_Northbound,NB_Global,connections",
|
||||
"--ssl-protocols=db:OVN_Northbound,SSL,ssl_protocols",
|
||||
"--ssl-ciphers=db:OVN_Northbound,SSL,ssl_ciphers"))
|
||||
def start_ovsdb_processes(self):
|
||||
super().start_ovsdb_processes()
|
||||
data = [
|
||||
(self.ovnnb_connection,
|
||||
"OVN_Northbound", "ovnnb", "NB_Global"),
|
||||
(self.ovnsb_connection,
|
||||
"OVN_Southbound", "ovnsb", "SB_Global")]
|
||||
|
||||
self.ovnsb_server = self.useFixture(OvsdbServerFixture(
|
||||
self.venv, "ovnsb_db", self.ovnsb_schema, self.ovsdir,
|
||||
"--remote=db:OVN_Southbound,SB_Global,connections",
|
||||
"--ssl-protocols=db:OVN_Southbound,SSL,ssl_protocols",
|
||||
"--ssl-ciphers=db:OVN_Southbound,SSL,ssl_ciphers"))
|
||||
|
||||
self.northd = self.useFixture(NorthdFixture(
|
||||
self.venv, self.ovnnb_connection, self.ovnsb_connection))
|
||||
|
||||
self.controller = self.useFixture(OvnControllerFixture(self.venv))
|
||||
super()._setUp()
|
||||
for connection, schema, db_name, table in data:
|
||||
self.call(['ovsdb-server',
|
||||
'--detach', '--no-chdir', '-vconsole:off',
|
||||
'--pidfile=%s' % os.path.join(self.venv,
|
||||
'%s_db.pid' % (db_name)),
|
||||
'--log-file=%s' % os.path.join(self.venv,
|
||||
'%s_db.log' % (db_name)),
|
||||
'--remote=db:%s,%s,connections' % (schema, table),
|
||||
'--private-key=db:%s,SSL,private_key' % (schema),
|
||||
'--certificate=db:%s,SSL,certificate' % (schema),
|
||||
'--ca-cert=db:%s,SSL,ca_cert' % (schema),
|
||||
'--ssl-protocols=db:%s,SSL,ssl_protocols' % (schema),
|
||||
'--ssl-ciphers=db:%s,SSL,ssl_ciphers' % (schema),
|
||||
'--remote=p' + connection, '%s.db' % (db_name)])
|
||||
|
||||
def init_processes(self):
|
||||
super().init_processes()
|
||||
self.venv.call(["ovn-nbctl", "init"])
|
||||
self.venv.call(["ovn-sbctl", "init"])
|
||||
self.call(['ovn-nbctl', 'init'])
|
||||
self.call(['ovn-sbctl', 'init'])
|
||||
if self.add_chassis:
|
||||
self.venv.call([
|
||||
"ovs-vsctl", f"--db={self.ovsdb_server.connection}",
|
||||
"set", "open", ".",
|
||||
"external_ids:system-id=56b18105-5706-46ef-80c4-ff20979ab068",
|
||||
"external_ids:hostname=sandbox",
|
||||
"external_ids:ovn-encap-type=geneve",
|
||||
"external_ids:ovn-encap-ip=127.0.0.1"])
|
||||
self.call([
|
||||
'ovs-vsctl', 'set', 'open', '.',
|
||||
'external_ids:system-id=56b18105-5706-46ef-80c4-ff20979ab068',
|
||||
'external_ids:hostname=sandbox',
|
||||
'external_ids:ovn-encap-type=geneve',
|
||||
'external_ids:ovn-encap-ip=127.0.0.1'])
|
||||
# TODO(twilson) SSL stuff
|
||||
self.venv.call([
|
||||
"ovs-vsctl", f"--db={self.ovsdb_server.connection}",
|
||||
"set", "open", ".",
|
||||
"external_ids:ovn-remote=" + self.ovnsb_connection])
|
||||
self.call(['ovs-vsctl', 'set', 'open', '.',
|
||||
'external_ids:ovn-remote=' + self.ovnsb_connection])
|
||||
self.call(['ovn-northd', '--detach', '--no-chdir', '--pidfile',
|
||||
'-vconsole:off', '--log-file',
|
||||
'--ovnsb-db=' + self.ovnsb_connection,
|
||||
'--ovnnb-db=' + self.ovnnb_connection])
|
||||
self.call(['ovn-controller', '--detach', '--no-chdir', '--pidfile',
|
||||
'-vconsole:off', '--log-file'])
|
||||
|
||||
|
||||
class OvsOvnIcVenvFixture(OvsOvnVenvFixture):
|
||||
|
||||
def _setUp(self):
|
||||
if not self.has_icnb():
|
||||
return
|
||||
self.ovn_icnb_server = self.useFixture(OvsdbServerFixture(
|
||||
self.venv, "ovn_ic_nb_db", self.ovn_icnb_schema, self.ovsdir,
|
||||
"--remote=db:OVN_IC_Northbound,IC_NB_Global,connections",
|
||||
"--ssl-protocols=db:OVN_IC_Northbound,SSL,ssl_protocols",
|
||||
"--ssl-ciphers=db:OVN_IC_Northbound,SSL,ssl_ciphers"))
|
||||
super()._setUp()
|
||||
if self.has_icnb():
|
||||
super()._setUp()
|
||||
|
||||
@property
|
||||
def ovn_icnb_connection(self):
|
||||
return self.ovn_icnb_server.connection
|
||||
return 'unix:' + os.path.join(self.venv, 'ovn_ic_nb_db.sock')
|
||||
|
||||
@property
|
||||
def ovn_icnb_schema(self):
|
||||
search_paths = (self.ovndir,) + self.OVN_PATHS
|
||||
return self.schema_path(search_paths, self.IC_NBSCHEMA)
|
||||
return os.path.join(self.ovndir, self.IC_NBSCHEMA)
|
||||
|
||||
def has_icnb(self):
|
||||
return os.path.isfile(self.ovn_icnb_schema)
|
||||
|
||||
def setup_dbs(self):
|
||||
super().setup_dbs()
|
||||
self.create_db('ovn_ic_nb.db', self.ovn_icnb_schema)
|
||||
|
||||
def start_ovsdb_processes(self):
|
||||
super().start_ovsdb_processes()
|
||||
connection, schema, db_name, table = (
|
||||
self.ovn_icnb_connection,
|
||||
"OVN_IC_Northbound", "ovn_ic_nb", "IC_NB_Global")
|
||||
self.call(['ovsdb-server',
|
||||
'--detach', '--no-chdir', '-vconsole:off',
|
||||
'--pidfile=%s' % os.path.join(self.venv,
|
||||
'%s_db.pid' % (db_name)),
|
||||
'--log-file=%s' % os.path.join(self.venv,
|
||||
'%s_db.log' % (db_name)),
|
||||
'--remote=db:%s,%s,connections' % (schema, table),
|
||||
'--private-key=db:%s,SSL,private_key' % (schema),
|
||||
'--certificate=db:%s,SSL,certificate' % (schema),
|
||||
'--ca-cert=db:%s,SSL,ca_cert' % (schema),
|
||||
'--ssl-protocols=db:%s,SSL,ssl_protocols' % (schema),
|
||||
'--ssl-ciphers=db:%s,SSL,ssl_ciphers' % (schema),
|
||||
'--remote=p' + connection, '%s.db' % (db_name)])
|
||||
|
||||
def init_processes(self):
|
||||
super().init_processes()
|
||||
self.venv.call(["ovn-ic-nbctl", "init"])
|
||||
self.call(['ovn-ic-nbctl', 'init'])
|
||||
|
||||
|
||||
class OvsVtepVenvFixture(OvsOvnVenvFixture):
|
||||
VTEP_SCHEMA = 'vtep.ovsschema'
|
||||
VTEP_DB = 'vtep.db'
|
||||
|
||||
def __init__(self, venv, **kwargs):
|
||||
super().__init__(venv, **kwargs)
|
||||
vtepdir = os.getenv('VTEP_SRCDIR') or ()
|
||||
vtepdir = os.getenv('VTEP_SRCDIR')
|
||||
if vtepdir and os.path.isdir(vtepdir):
|
||||
# Add VTEP source dir to venv paths
|
||||
self.venv.prepend_paths(vtepdir)
|
||||
self.vtepdir = vtepdir
|
||||
# Uses the existing OVS ovsdb-server fixture and passes in a second db
|
||||
self.ovsdb_server.create_db(self.VTEP_DB, self.vtep_schema)
|
||||
self.ovsdb_server.additional_dbs.append(self.VTEP_DB)
|
||||
self.PATH_VAR_TEMPLATE += ":{0}".format(vtepdir)
|
||||
self.vtepdir = self._share_path(self.OVS_PATHS, vtepdir,
|
||||
[self.VTEP_SCHEMA])
|
||||
super().__init__(venv, **kwargs)
|
||||
|
||||
def _setUp(self):
|
||||
if self.has_vtep:
|
||||
@@ -476,17 +296,20 @@ class OvsVtepVenvFixture(OvsOvnVenvFixture):
|
||||
|
||||
@property
|
||||
def vtep_schema(self):
|
||||
search_paths = (self.vtepdir,) + self.OVS_PATHS
|
||||
return self.schema_path(search_paths, self.VTEP_SCHEMA)
|
||||
return os.path.join(self.vtepdir, self.VTEP_SCHEMA)
|
||||
|
||||
@property
|
||||
def has_vtep(self):
|
||||
return os.path.isfile(self.vtep_schema)
|
||||
|
||||
def setup_dbs(self):
|
||||
db_filename = 'vtep.conf'
|
||||
super().setup_dbs()
|
||||
self.create_db(db_filename, self.vtep_schema)
|
||||
self.ovsdb_server_dbs.append(db_filename)
|
||||
|
||||
def init_processes(self):
|
||||
super().init_processes()
|
||||
# there are no 'init' method in vtep-ctl,
|
||||
# but record in 'Global' table is needed
|
||||
self.venv.call(["vtep-ctl",
|
||||
f"--db={self.ovsdb_server.connection}",
|
||||
"show"])
|
||||
self.call(['vtep-ctl', 'show'])
|
||||
|
||||
Reference in New Issue
Block a user