-# Copyright 2015 Intel Corporation.
+# Copyright 2015-2016 Intel Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
import os
import logging
import string
+import re
from tools import tasks
from conf import settings
'ovs-vsctl')
_OVS_OFCTL_BIN = os.path.join(settings.getValue('OVS_DIR'), 'utilities',
'ovs-ofctl')
+_OVS_APPCTL_BIN = os.path.join(settings.getValue('OVS_DIR'), 'utilities',
+ 'ovs-appctl')
_OVS_BRIDGE_NAME = settings.getValue('VSWITCH_BRIDGE_NAME')
def run_vsctl(self, args, check_error=False):
"""Run ``ovs-vsctl`` with supplied arguments.
+ In case that timeout is set to -1, then ovs-vsctl
+ will be called with --no-wait option.
+
:param args: Arguments to pass to ``ovs-vsctl``
:param check_error: Throw exception on error
:return: None
"""
- cmd = ['sudo', _OVS_VSCTL_BIN, '--timeout', str(self.timeout)] + args
+ if self.timeout == -1:
+ cmd = ['sudo', _OVS_VSCTL_BIN, '--no-wait'] + args
+ else:
+ cmd = ['sudo', _OVS_VSCTL_BIN, '--timeout', str(self.timeout)] + args
return tasks.run_task(
cmd, self.logger, 'Running ovs-vsctl...', check_error)
+
+ def run_appctl(self, args, check_error=False):
+ """Run ``ovs-appctl`` with supplied arguments.
+
+ :param args: Arguments to pass to ``ovs-appctl``
+ :param check_error: Throw exception on error
+
+ :return: None
+ """
+ cmd = ['sudo', _OVS_APPCTL_BIN,
+ '--timeout',
+ str(self.timeout)] + args
+ return tasks.run_task(
+ cmd, self.logger, 'Running ovs-appctl...', check_error)
+
+
# datapath management
def add_br(self, br_name=_OVS_BRIDGE_NAME, params=None):
self.logger.debug('delete bridge')
self.run_vsctl(['del-br', br_name])
+ # Route and ARP functions
+
+ def add_route(self, network, destination):
+ """Add route to tunneling routing table.
+
+ :param network: Network
+ :param destination: Gateway
+
+ :return: None
+ """
+ self.logger.debug('add ovs/route')
+ self.run_appctl(['ovs/route/add', network, destination])
+
+
+ def set_tunnel_arp(self, ip_addr, mac_addr, br_name=_OVS_BRIDGE_NAME):
+ """Add OVS arp entry for tunneling
+
+ :param ip: IP of bridge
+ :param mac_addr: MAC address of the bridge
+ :param br_name: Name of the bridge
+
+ :return: None
+ """
+ self.logger.debug('tnl/arp/set')
+ self.run_appctl(['tnl/arp/set', br_name, ip_addr, mac_addr])
+
class OFBridge(OFBase):
"""Control a bridge instance using ``ovs-vsctl`` and ``ovs-ofctl``.
field_params.append('%(field)s=%(value)s' %
{'field': key, 'value': default})
- field_params = ','.join(field_params)
+ field_params_str = ','.join(field_params)
_flow_key_param = {
- 'fields': field_params,
+ 'fields': field_params_str,
}
# no actions == delete key
flow_str = _flow_del_key.substitute(_flow_key_param)
return flow_str
+
+def flow_match(flow_dump, flow_src):
+ """ Compares two flows
+
+ :param flow_dump: string - a string with flow obtained by ovs-ofctl dump-flows
+ :param flow_src: string - a string with flow obtained by call of flow_key()
+
+ :return: boolean
+ """
+ # perform unifications on both source and destination flows
+ flow_dump = flow_dump.replace('actions=', 'action=')
+ flow_src = flow_src.replace('actions=', 'action=')
+
+ # split flow strings into lists of comparable elements
+ flow_dump_list = re.findall(r"[\w.:=()]+", flow_dump)
+ flow_src_list = re.findall(r"[\w.:=()]+", flow_src)
+
+ # check if all items from source flow are present in dump flow
+ flow_src_ctrl = list(flow_src_list)
+ for rule in flow_src_list:
+ if rule in flow_dump_list:
+ flow_src_ctrl.remove(rule)
+ return True if not len(flow_src_ctrl) else False