Skip to content

Commit

Permalink
ovs-xapi-sync: Add unit test.
Browse files Browse the repository at this point in the history
  • Loading branch information
blp committed Sep 26, 2011
1 parent b54bdbe commit 1b0fdca
Show file tree
Hide file tree
Showing 5 changed files with 189 additions and 11 deletions.
89 changes: 89 additions & 0 deletions tests/MockXenAPI.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Copyright (c) 2011 Nicira Networks
#
# 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.

def xapi_local():
return Session()


class Session(object):
def __init__(self):
self.xenapi = XenAPI()


class Failure(Exception):
pass


class XenAPI(object):
def __init__(self):
self.network = Network()
self.pool = Pool()
self.VIF = VIF()

def login_with_password(self, unused_username, unused_password):
pass


class RecordRef(object):
def __init__(self, attrs):
self.attrs = attrs


class Table(object):
def __init__(self, records):
self.records = records

def get_all(self):
return [RecordRef(rec) for rec in self.records]

def get_by_uuid(self, uuid):
recs = [rec for rec in self.records if rec["uuid"] == uuid]
if len(recs) != 1:
raise Failure("No record with UUID %s" % uuid)
return RecordRef(recs[0])

def get_record(self, record_ref):
return record_ref.attrs


class Network(Table):
__records = ({"uuid": "9b66c68b-a74e-4d34-89a5-20a8ab352d1e",
"bridge": "xenbr0",
"other_config":
{"vswitch-controller-fail-mode": "secure",
"nicira-bridge-id": "custom bridge ID"}},
{"uuid": "e1c9019d-375b-45ac-a441-0255dd2247de",
"bridge": "xenbr1",
"other_config":
{"vswitch-disable-in-band": "true"}})

def __init__(self):
Table.__init__(self, Network.__records)


class Pool(Table):
__records = ({"uuid": "7a793edf-e5f4-4994-a0f9-cee784c0cda3",
"other_config":
{"vswitch-controller-fail-mode": "secure"}},)

def __init__(self):
Table.__init__(self, Pool.__records)

class VIF(Table):
__records = ({"uuid": "6ab1b260-398e-49ba-827b-c7696108964c",
"other_config":
{"nicira-iface-id": "custom iface ID"}},)

def __init__(self):
Table.__init__(self, VIF.__records)
4 changes: 3 additions & 1 deletion tests/automake.mk
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ TESTSUITE_AT = \
tests/ovsdb-idl.at \
tests/ovs-vsctl.at \
tests/ovs-monitor-ipsec.at \
tests/ovs-xapi-sync.at \
tests/interface-reconfigure.at
TESTSUITE = $(srcdir)/tests/testsuite
DISTCLEANFILES += tests/atconfig tests/atlocal
Expand Down Expand Up @@ -335,7 +336,8 @@ EXTRA_DIST += \
tests/test-json.py \
tests/test-jsonrpc.py \
tests/test-ovsdb.py \
tests/test-reconnect.py
tests/test-reconnect.py \
tests/MockXenAPI.py

if HAVE_OPENSSL
TESTPKI_FILES = \
Expand Down
74 changes: 74 additions & 0 deletions tests/ovs-xapi-sync.at
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
AT_BANNER([ovs-xapi-sync])

AT_SETUP([ovs-xapi-sync])
AT_SKIP_IF([test $HAVE_PYTHON = no])

# Mock up the XenAPI.
cp "$top_srcdir/tests/MockXenAPI.py" XenAPI.py
PYTHONPATH=`pwd`:$PYTHONPATH
export PYTHONPATH

OVS_PKGDATADIR=`pwd`; export OVS_PKGDATADIR
cp "$top_srcdir/vswitchd/vswitch.ovsschema" .

cp "$top_srcdir/xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync" \
ovs-xapi-sync

trap 'kill `cat pid ovs-xapi-sync.pid`' 0

mkdir var var/run
touch var/run/xapi_init_complete.cookie

ovs_vsctl () {
ovs-vsctl --timeout=5 --no-wait -vreconnect:ANY:emer --db=unix:socket "$@"
}

# Start ovsdb-server.
OVS_VSCTL_SETUP

# Start ovs-xapi-sync.
AT_CHECK([$PYTHON ./ovs-xapi-sync "--pidfile-name=`pwd`/ovs-xapi-sync.pid" \
"--root-prefix=`pwd`" unix:socket >log 2>&1 &])
AT_CAPTURE_FILE([log])

# Add bridges and check ovs-xapi-sync's work.
AT_CHECK([ovs_vsctl -- add-br xenbr0 -- add-br xenbr1])
OVS_WAIT_UNTIL([test "X`ovs_vsctl get bridge xenbr0 fail-mode`" != "X[[]]"])
AT_CHECK([ovs_vsctl \
-- get bridge xenbr0 fail-mode other-config external-ids \
-- get bridge xenbr1 fail-mode other-config external-ids], [0],
[[secure
{}
{bridge-id="custom bridge ID"}
secure
{disable-in-band="true"}
{}
]])

# Add vif and check daemon's work.
AT_CHECK([ovs_vsctl \
-- add-port xenbr0 vif1.0 \
-- set Interface vif1.0 'external-ids={attached-mac="00:11:22:33:44:55", xs-network-uuid="9b66c68b-a74e-4d34-89a5-20a8ab352d1e", xs-vif-uuid="6ab1b260-398e-49ba-827b-c7696108964c", xs-vm-uuid="fcb8a3f6-dc04-41d2-8b8a-55afd2b755b8"'}])
OVS_WAIT_UNTIL([ovs_vsctl get interface vif1.0 external-ids:iface-id >/dev/null 2>&1])
AT_CHECK([ovs_vsctl get interface vif1.0 external-ids], [0],
[{attached-mac="00:11:22:33:44:55", iface-id="custom iface ID", iface-status=active, xs-network-uuid="9b66c68b-a74e-4d34-89a5-20a8ab352d1e", xs-vif-uuid="6ab1b260-398e-49ba-827b-c7696108964c", xs-vm-uuid="fcb8a3f6-dc04-41d2-8b8a-55afd2b755b8"}
])

# Add corresponding tap and check daemon's work.
AT_CHECK([ovs_vsctl add-port xenbr0 tap1.0])
OVS_WAIT_UNTIL([ovs_vsctl get interface tap1.0 external-ids:iface-id >/dev/null 2>&1])
AT_CHECK([ovs_vsctl \
-- get interface vif1.0 external-ids \
-- get interface tap1.0 external-ids], [0],
[{attached-mac="00:11:22:33:44:55", iface-id="custom iface ID", iface-status=inactive, xs-network-uuid="9b66c68b-a74e-4d34-89a5-20a8ab352d1e", xs-vif-uuid="6ab1b260-398e-49ba-827b-c7696108964c", xs-vm-uuid="fcb8a3f6-dc04-41d2-8b8a-55afd2b755b8"}
{attached-mac="00:11:22:33:44:55", iface-id="custom iface ID", iface-status=active, xs-network-uuid="9b66c68b-a74e-4d34-89a5-20a8ab352d1e", xs-vif-uuid="6ab1b260-398e-49ba-827b-c7696108964c", xs-vm-uuid="fcb8a3f6-dc04-41d2-8b8a-55afd2b755b8"}
])

# Remove corresponding tap and check daemon's work.
AT_CHECK([ovs_vsctl del-port tap1.0])
OVS_WAIT_UNTIL([test `ovs_vsctl get interface vif1.0 external-ids:iface-status` = active])
AT_CHECK([ovs_vsctl get interface vif1.0 external-ids], [0],
[{attached-mac="00:11:22:33:44:55", iface-id="custom iface ID", iface-status=active, xs-network-uuid="9b66c68b-a74e-4d34-89a5-20a8ab352d1e", xs-vif-uuid="6ab1b260-398e-49ba-827b-c7696108964c", xs-vm-uuid="fcb8a3f6-dc04-41d2-8b8a-55afd2b755b8"}
])

AT_CLEANUP
1 change: 1 addition & 0 deletions tests/testsuite.at
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,5 @@ m4_include([tests/ofproto-dpif.at])
m4_include([tests/ovsdb.at])
m4_include([tests/ovs-vsctl.at])
m4_include([tests/ovs-monitor-ipsec.at])
m4_include([tests/ovs-xapi-sync.at])
m4_include([tests/interface-reconfigure.at])
32 changes: 22 additions & 10 deletions xenserver/usr_share_openvswitch_scripts_ovs-xapi-sync
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import ovs.util
import ovs.daemon
import ovs.db.idl

root_prefix = '' # Prefix for absolute file names, for testing.
s_log = logging.getLogger("ovs-xapi-sync")
vsctl = "/usr/bin/ovs-vsctl"
session = None
Expand All @@ -59,9 +60,9 @@ def init_session():
try:
session = XenAPI.xapi_local()
session.xenapi.login_with_password("", "")
except:
except XenAPI.Failure, e:
session = None
s_log.warning("Couldn't login to XAPI")
s_log.warning("Couldn't login to XAPI (%s)" % e)
return False

return True
Expand Down Expand Up @@ -218,8 +219,10 @@ def usage():
print "usage: %s [OPTIONS] DATABASE" % sys.argv[0]
print "where DATABASE is a socket on which ovsdb-server is listening."
ovs.daemon.usage()
print "Other options:"
print " -h, --help display this help message"
print """\
Other options:
--root-prefix=DIR Use DIR as alternate root directory (for testing).
-h, --help display this help message"""
sys.exit(0)


Expand All @@ -232,23 +235,31 @@ def handler(signum, _):
def main(argv):
global force_run

l_handler = logging.handlers.RotatingFileHandler(
s_log.addHandler(logging.StreamHandler())
try:
l_handler = logging.handlers.RotatingFileHandler(
"/var/log/openvswitch/ovs-xapi-sync.log")
l_formatter = logging.Formatter('%(filename)s: %(levelname)s: %(message)s')
l_handler.setFormatter(l_formatter)
s_log.addHandler(l_handler)
l_formatter = logging.Formatter('%(filename)s: %(levelname)s: %(message)s')
l_handler.setFormatter(l_formatter)
s_log.addHandler(l_handler)
except IOError, e:
logging.basicConfig()
s_log.warn("failed to open logfile (%s)" % e)
s_log.setLevel(logging.INFO)

try:
options, args = getopt.gnu_getopt(
argv[1:], 'h', ['help'] + ovs.daemon.LONG_OPTIONS)
argv[1:], 'h', ['help', 'root-prefix='] + ovs.daemon.LONG_OPTIONS)
except getopt.GetoptError, geo:
sys.stderr.write("%s: %s\n" % (ovs.util.PROGRAM_NAME, geo.msg))
sys.exit(1)

for key, value in options:
if key in ['-h', '--help']:
usage()
elif key == '--root-prefix':
global root_prefix
root_prefix = value
elif not ovs.daemon.parse_opt(key, value):
sys.stderr.write("%s: unhandled option %s\n"
% (ovs.util.PROGRAM_NAME, key))
Expand All @@ -269,7 +280,8 @@ def main(argv):

# This daemon is usually started before XAPI, but to complete our
# tasks, we need it. Wait here until it's up.
while not os.path.exists("/var/run/xapi_init_complete.cookie"):
cookie_file = root_prefix + "/var/run/xapi_init_complete.cookie"
while not os.path.exists(cookie_file):
time.sleep(1)

signal.signal(signal.SIGHUP, handler)
Expand Down

0 comments on commit 1b0fdca

Please sign in to comment.