Seamless shit for dhcpl2relay.
It never looked to have been seamless before.
Anyway, now after setup.
run -m <> -t dhcpl2relay:dhcpl2relay_exchange.test_dhcpl2relay_initialize
to bootstrap the relay.
Then one can try firing the test from the olt node or same node.
Supports 1 subscriber dhcp.
You are supposed to run the tls test actually.
But there is support in dhcpl2relay app itself to provision the olt subscribers (vlans)
Change-Id: Ibcdf3bf4f0962d174f245ca914b97c644001d729
diff --git a/src/test/dhcpl2relay/dhcpl2relayTest.py b/src/test/dhcpl2relay/dhcpl2relayTest.py
index a269f75..3917a45 100644
--- a/src/test/dhcpl2relay/dhcpl2relayTest.py
+++ b/src/test/dhcpl2relay/dhcpl2relayTest.py
@@ -36,10 +36,10 @@
import time
import os, sys
from DHCP import DHCPTest
-from CordTestUtils import get_mac, log_test
+from CordTestUtils import get_mac, log_test, getstatusoutput, get_controller
from OnosCtrl import OnosCtrl
from OltConfig import OltConfig
-from CordTestServer import cord_test_onos_restart
+from CordTestServer import cord_test_onos_restart, cord_test_ovs_flow_add
from CordTestConfig import setup_module, teardown_module
from CordLogger import CordLogger
from portmaps import g_subscriber_port_map
@@ -47,6 +47,7 @@
from VolthaCtrl import VolthaCtrl
import threading, random
from threading import current_thread
+import requests
log_test.setLevel('INFO')
class dhcpl2relay_exchange(CordLogger):
@@ -62,13 +63,15 @@
sadis_app = 'org.opencord.sadis'
app_dhcp = 'org.onosproject.dhcp'
app_olt = 'org.onosproject.olt'
+ relay_interfaces = ()
relay_interfaces_last = ()
interface_to_mac_map = {}
+ relay_vlan_map = {}
host_ip_map = {}
test_path = os.path.dirname(os.path.realpath(__file__))
dhcp_data_dir = os.path.join(test_path, '..', 'setup')
dhcpl2_app_file = os.path.join(test_path, '..', 'apps/dhcpl2relay-1.0.0.oar')
- olt_app_file = os.path.join(test_path, '..', 'apps/olt-app-1.3.0-SNAPSHOT.oar')
+ olt_app_file = os.path.join(test_path, '..', 'apps/olt-app-3.0-SNAPSHOT.oar')
sadis_app_file = os.path.join(test_path, '..', 'apps/sadis-app-1.0.0-SNAPSHOT.oar')
olt_conf_file = os.getenv('OLT_CONFIG_FILE', os.path.join(test_path, '..', 'setup/olt_config_voltha_local.json'))
default_config = { 'default-lease-time' : 600, 'max-lease-time' : 7200, }
@@ -100,6 +103,7 @@
configs = {}
sadis_configs = {}
default_onos_netcfg = {}
+ voltha_switch_map = None
@classmethod
def update_apps_version(cls):
@@ -107,21 +111,10 @@
major = int(version.split('.')[0])
minor = int(version.split('.')[1])
dhcpl2_app_version = '1.0.0'
- sadis_app_version = '1.0.0-SNAPSHOT'
-# sadis-app-1.0.0-SNAPSHOT.oar
-# if major > 1:
-# cordigmp_app_version = '3.0-SNAPSHOT'
-# olt_app_version = '2.0-SNAPSHOT'
-# elif major == 1:
-# if minor > 10:
-# cordigmp_app_version = '3.0-SNAPSHOT'
-# olt_app_version = '2.0-SNAPSHOT'
-# elif minor <= 8:
-# olt_app_version = '1.1-SNAPSHOT'
+ sadis_app_version = '3.0-SNAPSHOT'
cls.dhcpl2_app_file = os.path.join(cls.test_path, '..', 'apps/dhcpl2relay-{}.oar'.format(dhcpl2_app_version))
cls.sadis_app_file = os.path.join(cls.test_path, '..', 'apps/sadis-app-{}.oar'.format(sadis_app_version))
-
@classmethod
def setUpClass(cls):
''' Activate the cord dhcpl2relay app'''
@@ -132,49 +125,179 @@
status, _ = cls.onos_ctrl.activate()
#assert_equal(status, True)
time.sleep(3)
- cls.onos_ctrl = OnosCtrl(cls.sadis_app)
- status, _ = cls.onos_ctrl.activate()
+ status, _ = OnosCtrl(cls.sadis_app).activate()
#assert_equal(status, True)
time.sleep(3)
- cls.dhcp_l2_relay_setup()
- cls.cord_sadis_load()
- cls.cord_l2_relay_load()
- ##start dhcpd initially with default config
- #cls.dhcpd_start()
+ cls.setup_dhcpd()
def setUp(self):
self.default_onos_netcfg = OnosCtrl.get_config()
super(dhcpl2relay_exchange, self).setUp()
- self.dhcp_l2_relay_setup()
- self.cord_sadis_load()
- self.cord_l2_relay_load()
+ #self.dhcp_l2_relay_setup()
+ #self.cord_sadis_load()
+ #self.cord_l2_relay_load()
def tearDown(self):
super(dhcpl2relay_exchange, self).tearDown()
- OnosCtrl.uninstall_app(self.dhcpl2_app_file)
- OnosCtrl.uninstall_app(self.sadis_app_file)
- OnosCtrl.uninstall_app(self.olt_app_file)
+ #OnosCtrl.uninstall_app(self.dhcpl2_app_file)
+ #OnosCtrl.uninstall_app(self.sadis_app_file)
+ #OnosCtrl.uninstall_app(self.olt_app_file)
@classmethod
def tearDownClass(cls):
'''Deactivate the cord dhcpl2relay app'''
-# OnosCtrl.uninstall_app(cls.dhcpl2_app_file)
-# OnosCtrl.uninstall_app(cls.sadis_app_file)
- cls.onos_ctrl.deactivate()
- # OnosCtrl(cls.app).deactivate()
- OnosCtrl(cls.sadis_app).deactivate()
- OnosCtrl(cls.app_olt).deactivate()
- #cls.dhcp_l2_relay_cleanup()
+ #cls.onos_ctrl.deactivate()
+ #OnosCtrl(cls.sadis_app).deactivate()
+ #OnosCtrl(cls.app_olt).deactivate()
+
+ @classmethod
+ def setup_dhcpd(cls, boot_delay = 5):
+ if cls.service_running("/usr/sbin/dhcpd"):
+ print('DHCPD already running in container')
+ return True
+ setup_for_relay = cls.dhcp_l2_relay_setup()
+ cls.cord_l2_relay_load()
+ cls.voltha_setup()
+ dhcp_start_status = cls.dhcpd_start()
+ if setup_for_relay and dhcp_start_status:
+ return True
+ return False
+
+ @classmethod
+ def config_olt(cls, switch_map):
+ controller = get_controller()
+ auth = ('karaf', 'karaf')
+ #configure subscriber for every port on all the voltha devices
+ for device, device_map in switch_map.iteritems():
+ uni_ports = device_map['ports']
+ uplink_vlan = device_map['uplink_vlan']
+ for port in uni_ports:
+ vlan = port
+ rest_url = 'http://{}:8181/onos/olt/oltapp/{}/{}/{}'.format(controller,
+ device,
+ port,
+ vlan)
+ requests.post(rest_url, auth = auth)
+
+ @classmethod
+ def voltha_setup(cls):
+ s_tag_map = {}
+ #configure olt app to provision dhcp flows
+ cls.config_olt(cls.voltha_switch_map)
+ for switch, switch_map in cls.voltha_switch_map.iteritems():
+ s_tag_map[int(switch_map['uplink_vlan'])] = map(lambda p: int(p), switch_map['ports'])
+
+ cmd_list = []
+ relay_interface = cls.relay_interfaces[0]
+ cls.relay_vlan_map[relay_interface] = []
+ for s_tag, ports in s_tag_map.iteritems():
+ vlan_stag_intf = '{}.{}'.format(relay_interface, s_tag)
+ cmd = 'ip link add link %s name %s type vlan id %d' %(relay_interface, vlan_stag_intf, s_tag)
+ cmd_list.append(cmd)
+ cmd = 'ip link set %s up' %(vlan_stag_intf)
+ cmd_list.append(cmd)
+ for port in ports:
+ vlan_ctag_intf = '{}.{}.{}'.format(relay_interface, s_tag, port)
+ cmd = 'ip link add link %s name %s type vlan id %d' %(vlan_stag_intf, vlan_ctag_intf, port)
+ cmd_list.append(cmd)
+ cmd = 'ip link set %s up' %(vlan_ctag_intf)
+ cmd_list.append(cmd)
+ cls.relay_vlan_map[relay_interface].append(vlan_ctag_intf)
+ cls.relay_vlan_map[relay_interface].append(vlan_stag_intf)
+
+ for cmd in cmd_list:
+ log_test.info('Running command: %s' %cmd)
+ os.system(cmd)
+
+ cord_test_ovs_flow_add(cls.relay_interface_port)
+ for s_tag in s_tag_map.keys():
+ log_test.info('Configuring OVS flow for port %d, s_tag %d' %(cls.relay_interface_port, s_tag))
+ cord_test_ovs_flow_add(cls.relay_interface_port, s_tag)
+
+ @classmethod
+ def service_running(cls, pattern):
+ st, _ = getstatusoutput('pgrep -f "{}"'.format(pattern))
+ return True if st == 0 else False
+
+ @classmethod
+ def dhcpd_conf_generate(cls, config = default_config, options = default_options,
+ subnet = default_subnet_config):
+ conf = ''
+ for k, v in config.items():
+ conf += '{} {};\n'.format(k, v)
+
+ opts = ''
+ for k, v in options:
+ opts += 'option {} {};\n'.format(k, v)
+
+ subnet_config = ''
+ for _, v in subnet:
+ subnet_config += '{}\n'.format(v)
+
+ return '{}{}{}'.format(conf, opts, subnet_config)
+
+ @classmethod
+ def dhcpd_start(cls, intf_list = None,
+ config = default_config, options = default_options,
+ subnet = default_subnet_config):
+ '''Start the dhcpd server by generating the conf file'''
+ if intf_list is None:
+ intf_list = cls.relay_interfaces
+ intf_list = list(intf_list)
+ ##stop dhcpd if already running
+ #cls.dhcpd_stop()
+ dhcp_conf = cls.dhcpd_conf_generate(config = config, options = options,
+ subnet = subnet)
+ ##first touch dhcpd.leases if it doesn't exist
+ lease_file = '{}/dhcpd.leases'.format(cls.dhcp_data_dir)
+ if os.access(lease_file, os.F_OK) is False:
+ with open(lease_file, 'w') as fd: pass
+
+ conf_file = '{}/dhcpd.conf'.format(cls.dhcp_data_dir)
+ with open(conf_file, 'w') as fd:
+ fd.write(dhcp_conf)
+
+ #now configure the dhcpd interfaces for various subnets
+ index = 0
+ intf_info = []
+ vlan_intf_list = []
+ for ip,_ in subnet:
+ vlan_intf = None
+ intf = intf_list[index]
+ if intf in cls.relay_vlan_map:
+ vlan_intf = cls.relay_vlan_map[intf][0]
+ vlan_intf_list.append(vlan_intf)
+ mac = cls.get_mac(intf)
+ intf_info.append((ip, mac))
+ index += 1
+ cmd = 'ifconfig {} {}'.format(intf, ip)
+ status = os.system(cmd)
+ if vlan_intf:
+ cmd = 'ifconfig {} {}'.format(vlan_intf, ip)
+ os.system(cmd)
+
+ intf_str = ','.join(intf_list)
+ dhcpd_cmd = '/usr/sbin/dhcpd -4 --no-pid -cf {0} -lf {1} {2}'.format('/root/test/src/test/setup/dhcpd.conf','/root/test/src/test/setup/dhcpd.leases', intf_str)
+ print('Starting DHCPD server with command: %s' %dhcpd_cmd)
+ status = os.system(dhcpd_cmd)
+ vlan_intf_str = ','.join(vlan_intf_list)
+ dhcpd_cmd = '/usr/sbin/dhcpd -4 --no-pid -cf {0} -lf {1} {2}'.format('/root/test/src/test/setup/dhcpd.conf','/root/test/src/test/setup/dhcpd.leases', vlan_intf_str)
+ print('Starting DHCPD server with command: %s' %dhcpd_cmd)
+ status = os.system(dhcpd_cmd)
+ if status > 255:
+ status = 1
+ else:
+ return False
+ time.sleep(3)
+ cls.relay_interfaces_last = cls.relay_interfaces
+ cls.relay_interfaces = intf_list
+ return True
@classmethod
def dhcp_l2_relay_setup(cls):
- did = OnosCtrl.get_device_ids()
- device_details = OnosCtrl.get_devices()
+ device_details = OnosCtrl.get_devices(mfr = 'Nicira')
if device_details is not None:
- for device in device_details:
- ## Assuming only one OVS is detected on ONOS and its for external DHCP server connect point...
- if device['available'] is True and device['driver'] == 'ovs':
- did_ovs = device['id']
+ did_ovs = device_details[0]['id']
else:
log_test.info('On this DHCPl2relay setup, onos does not have ovs device where external DHCP server is have connect point, so return with false status')
return False
@@ -208,7 +331,7 @@
relay_ip = cls.get_host_ip(interface_list[0][0])
relay_mac = cls.get_mac(cls.port_map[cls.relay_interface_port])
interface_list.append((cls.relay_interface_port, relay_ip, relay_mac))
- #cls.onos_interface_load(interface_list)
+ cls.onos_interface_load(interface_list)
@classmethod
def dhcp_l2_relay_cleanup(cls):
@@ -254,32 +377,17 @@
cls.configs['interface_config'] = interface_dict
@classmethod
- def cord_l2_relay_load(cls,dhcp_server_connectPoint = None, delete = False):
+ def cord_l2_relay_load(cls, dhcp_server_connectPoint = None, delete = False):
OnosCtrl.uninstall_app(cls.dhcpl2_app_file)
- #relay_device_map = '{}/{}'.format(cls.relay_device_id, cls.relay_interface_port)
+ relay_device_map = '{}/{}'.format(cls.relay_device_id, cls.relay_interface_port)
#### We have to work on later versions by removing these hard coded values
- relay_device_map = "{}/1".format(cls.relay_device_id)
- relay_device_map3 = "{}/3".format(cls.relay_device_id)
- relay_device_map4 = "{}/4".format(cls.relay_device_id)
- relay_device_map5 = "{}/5".format(cls.relay_device_id)
- relay_device_map6 = "{}/6".format(cls.relay_device_id)
- relay_device_map7 = "{}/7".format(cls.relay_device_id)
- relay_device_map8 = "{}/8".format(cls.relay_device_id)
- relay_device_map9 = "{}/9".format(cls.relay_device_id)
- relay_device_map10 = "{}/10".format(cls.relay_device_id)
- relay_device_map11 = "{}/11".format(cls.relay_device_id)
- relay_device_map12 = "{}/12".format(cls.relay_device_id)
if dhcp_server_connectPoint is None:
- dhcp_server_connectPoint = [relay_device_map,relay_device_map3,relay_device_map4,relay_device_map5,relay_device_map6,relay_device_map7,relay_device_map8,relay_device_map9,relay_device_map10,relay_device_map11,relay_device_map12]
- print relay_device_map
+ dhcp_server_connectPoint = [relay_device_map]
dhcp_dict = { "apps" : { "org.opencord.dhcpl2relay" : {"dhcpl2relay" :
- {"dhcpserverConnectPoint":dhcp_server_connectPoint}
+ {"dhcpServerConnectPoints":dhcp_server_connectPoint}
}
}
}
- print "---------------------------------------------"
- print dhcp_dict
- print "---------------------------------------------"
#OnosCtrl.uninstall_app(cls.dhcpl2_app_file)
OnosCtrl.install_app(cls.dhcpl2_app_file)
if delete == False:
@@ -461,6 +569,10 @@
(cip, sip, self.dhcp.get_mac(cip)[0]))
return cip,sip
+ def test_dhcpl2relay_initialize(self):
+ '''Setup and configure the DHCP L2 relay app'''
+ pass
+
def test_dhcpl2relay_with_one_request(self, iface = 'veth0'):
mac = self.get_mac(iface)
self.dhcp = DHCPTest(seed_ip = '10.10.10.1', iface = iface)
diff --git a/src/test/setup/cord-test.py b/src/test/setup/cord-test.py
index 18eeb71..81854d4 100755
--- a/src/test/setup/cord-test.py
+++ b/src/test/setup/cord-test.py
@@ -240,6 +240,7 @@
self.switch_started = True
def setup_dhcpd(self, manifest, boot_delay = 5):
+ return False
if not self.olt or not manifest.start_switch:
return False
if self.service_running("/usr/sbin/dhcpd"):
diff --git a/src/test/utils/CordTestServer.py b/src/test/utils/CordTestServer.py
index e495afb..6e1ae31 100644
--- a/src/test/utils/CordTestServer.py
+++ b/src/test/utils/CordTestServer.py
@@ -31,6 +31,8 @@
#
from CordContainer import Container, Onos, OnosStopWrapper, OnosCord, OnosCordStopWrapper, Quagga, QuaggaStopWrapper, Radius, reinitContainerClients
from OltConfig import OltConfig
+from OnosCtrl import OnosCtrl
+from CordTestUtils import get_controller
from EapolAAA import get_radius_macs, get_radius_networks
from nose.tools import nottest
from SimpleXMLRPCServer import SimpleXMLRPCServer
@@ -53,6 +55,17 @@
onos_cord = None
+ def __ovs_flow_add(self, in_port = 1, dl_vlan = 0):
+ if dl_vlan:
+ cmd = 'ovs-ofctl -O OpenFlow13 add-flow br-int in_port=%d,dl_vlan=%d,actions=CONTROLLER:65535' %(in_port, dl_vlan)
+ else:
+ cmd = 'ovs-ofctl -O OpenFlow13 add-flow br-int in_port=%d,actions=CONTROLLER:65535' %(in_port)
+ os.system(cmd)
+ return 'DONE'
+
+ def ovs_flow_add(self, kwargs):
+ return self.__ovs_flow_add(**kwargs)
+
def __restart_onos(self, node = None, config = None, timeout = 10):
if self.onos_cord:
onos_config = '{}/network-cfg.json'.format(self.onos_cord.onos_config_dir)
@@ -235,9 +248,10 @@
port = int(os.getenv('CORD_TEST_PORT', CORD_TEST_PORT))
return host, port
-def rpc_server_instance():
+def rpc_server_instance(host = None, port = None):
'''Stateless'''
- host, port = get_cord_test_loc()
+ if host is None or port is None:
+ host, port = get_cord_test_loc()
rpc_server = 'http://{}:{}'.format(host, port)
return xmlrpclib.Server(rpc_server, allow_none = True)
@@ -357,3 +371,26 @@
except: pass
return True
+
+@nottest
+def __cord_test_ovs_flow_add(**kwargs):
+ controller = get_controller()
+ OnosCtrl.config_extraneous_flows(controller = controller)
+ try:
+ return rpc_server_instance(host = controller, port = CORD_TEST_PORT).ovs_flow_add(kwargs)
+ except:
+ pass
+
+ try:
+ return rpc_server_instance().ovs_flow_add(kwargs)
+ except:
+ pass
+
+ return 'FAIL'
+
+@nottest
+def cord_test_ovs_flow_add(in_port, dl_vlan = 0):
+ data = __cord_test_ovs_flow_add(in_port = in_port, dl_vlan = dl_vlan)
+ if data == 'DONE':
+ return True
+ return False
diff --git a/src/test/utils/OnosCtrl.py b/src/test/utils/OnosCtrl.py
index 457c05b..f460450 100644
--- a/src/test/utils/OnosCtrl.py
+++ b/src/test/utils/OnosCtrl.py
@@ -461,3 +461,13 @@
cfg = dict(enableDhcpIgmpOnProvisioning = enableDhcpIgmpOnProvisioning, defaultVlan = defaultVlan)
resp = requests.post(property_url, auth = cls.auth, data = json.dumps(cfg))
return resp.ok, resp.status_code
+
+ @classmethod
+ def config_extraneous_flows(cls, controller = None, enable = True):
+ if controller is None:
+ controller = cls.controller
+ flow_property_url = 'configuration/org.onosproject.net.flow.impl.FlowRuleManager'
+ property_url = 'http://{}:8181/onos/v1/{}'.format(controller, flow_property_url)
+ cfg = dict(allowExtraneousRules = enable)
+ resp = requests.post(property_url, auth = cls.auth, data = json.dumps(cfg))
+ return resp.ok, resp.status_code