VOL-1666: BBSim DHCP Test Case

DHCP IP Addess assignment happens between BBSIM's dhclient, DHCP server
via dhcpl2relay. This is initiated automatically once all ONUs have been
AUTHORIZED.

For the Test Case, we simply verify that all ONUs were assigned an IP
address. We do this using the onos command 'dhcpl2relay-allocations'

A few other minor cleanups were also incorporated
- Dockerfile.onos 1.13.9-rc4 --> 1.13.9
- BBSim hold waits for all ONU's to be AUTHORIZED before proceeding

Change-Id: I863ee241aa904de8267f121fdeb8826298fc1491
diff --git a/docker/Dockerfile.onos b/docker/Dockerfile.onos
index 5973b43..425a96e 100644
--- a/docker/Dockerfile.onos
+++ b/docker/Dockerfile.onos
@@ -49,7 +49,7 @@
 RUN ./app-install.sh
 
 # Create the final image coping over the installed applications from the build stage
-FROM onosproject/onos:1.13.9-rc4
+FROM onosproject/onos:1.13.9
 MAINTAINER Open Networking Foundation <info@opennetworking.org>
 
 # The ENV settings must be replicated below as they are not shared between stages
diff --git a/tests/atests/build/dhcpl2relay_json b/tests/atests/build/dhcpl2relay_json
new file mode 100644
index 0000000..b417bbf
--- /dev/null
+++ b/tests/atests/build/dhcpl2relay_json
@@ -0,0 +1,7 @@
+{
+  "org.opencord.dhcpl2relay" : {
+    "dhcpl2relay" : {
+      "useOltUplinkForServerPktInOut" : true
+    }
+  }
+}
\ No newline at end of file
diff --git a/tests/atests/build/sadis_json b/tests/atests/build/sadis_json
index 1f32f0f..f817f30 100644
--- a/tests/atests/build/sadis_json
+++ b/tests/atests/build/sadis_json
@@ -19,162 +19,159 @@
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"BBSM00000100",
+          "id":"BBSM00000001",
           "cTag":55,
           "sTag":66,
-          "nasPortId":"BBSM00000100",
+          "nasPortId":"BBSM00000001",
           "technologyProfileId":64,
           "upstreamBandwidthProfile":"High-Speed-Internet",
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"BBSM00000101",
+          "id":"BBSM00000002",
           "cTag":56,
           "sTag":66,
-          "nasPortId":"BBSM00000101",
+          "nasPortId":"BBSM00000002",
           "technologyProfileId":64,
           "upstreamBandwidthProfile":"High-Speed-Internet",
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"BBSM00000102",
+          "id":"BBSM00000003",
           "cTag":57,
           "sTag":66,
-          "nasPortId":"BBSM00000102",
+          "nasPortId":"BBSM00000003",
           "technologyProfileId":64,
           "upstreamBandwidthProfile":"High-Speed-Internet",
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"BBSM00000103",
+          "id":"BBSM00000004",
           "cTag":58,
           "sTag":66,
-          "nasPortId":"BBSM00000103",
+          "nasPortId":"BBSM00000004",
           "technologyProfileId":64,
           "upstreamBandwidthProfile":"High-Speed-Internet",
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"BBSM00000104",
+          "id":"BBSM00000005",
           "cTag":60,
           "sTag":77,
-          "nasPortId":"BBSM00000104",
+          "nasPortId":"BBSM00000005",
           "technologyProfileId":64,
           "upstreamBandwidthProfile":"High-Speed-Internet",
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"BBSM00000105",
+          "id":"BBSM00000006",
           "cTag":61,
           "sTag":77,
-          "nasPortId":"BBSM00000105",
+          "nasPortId":"BBSM00000006",
           "technologyProfileId":64,
           "upstreamBandwidthProfile":"High-Speed-Internet",
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"BBSM00000106",
+          "id":"BBSM00000007",
           "cTag":62,
           "sTag":77,
-          "nasPortId":"BBSM00000106",
+          "nasPortId":"BBSM00000007",
           "technologyProfileId":64,
           "upstreamBandwidthProfile":"High-Speed-Internet",
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"BBSM00000107",
+          "id":"BBSM00000008",
           "cTag":63,
           "sTag":77,
-          "nasPortId":"BBSM00000107",
+          "nasPortId":"BBSM00000008",
           "technologyProfileId":64,
           "upstreamBandwidthProfile":"High-Speed-Internet",
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"BBSM00000108",
+          "id":"BBSM00000009",
           "cTag":70,
           "sTag":88,
-          "nasPortId":"BBSM00000108",
+          "nasPortId":"BBSM00000009",
           "technologyProfileId":64,
           "upstreamBandwidthProfile":"High-Speed-Internet",
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"BBSM00000109",
+          "id":"BBSM0000000a",
           "cTag":71,
           "sTag":88,
-          "nasPortId":"BBSM00000109",
+          "nasPortId":"BBSM0000000a",
           "technologyProfileId":64,
           "upstreamBandwidthProfile":"High-Speed-Internet",
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"BBSM0000010a",
+          "id":"BBSM0000000b",
           "cTag":72,
           "sTag":88,
-          "nasPortId":"BBSM0000010a",
+          "nasPortId":"BBSM0000000b",
           "technologyProfileId":64,
           "upstreamBandwidthProfile":"High-Speed-Internet",
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"BBSM0000010b",
+          "id":"BBSM0000000c",
           "cTag":73,
           "sTag":88,
-          "nasPortId":"BBSM0000010b",
+          "nasPortId":"BBSM0000000c",
           "technologyProfileId":64,
           "upstreamBandwidthProfile":"High-Speed-Internet",
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"BBSM0000010c",
+          "id":"BBSM0000000d",
           "cTag":80,
           "sTag":99,
-          "nasPortId":"BBSM0000010c",
+          "nasPortId":"BBSM0000000d",
           "technologyProfileId":64,
           "upstreamBandwidthProfile":"High-Speed-Internet",
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"BBSM0000010d",
+          "id":"BBSM0000000e",
           "cTag":81,
           "sTag":99,
-          "nasPortId":"BBSM0000010d",
+          "nasPortId":"BBSM0000000e",
           "technologyProfileId":64,
           "upstreamBandwidthProfile":"High-Speed-Internet",
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"BBSM0000010e",
+          "id":"BBSM0000000f",
           "cTag":82,
           "sTag":99,
-          "nasPortId":"BBSM0000010e",
+          "nasPortId":"BBSM0000000f",
           "technologyProfileId":64,
           "upstreamBandwidthProfile":"High-Speed-Internet",
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"BBSM0000010f",
+          "id":"BBSM00000010",
           "cTag":83,
           "sTag":99,
-          "nasPortId":"BBSM0000010f",
+          "nasPortId":"BBSM00000010",
           "technologyProfileId":64,
           "upstreamBandwidthProfile":"High-Speed-Internet",
           "downstreamBandwidthProfile":"User1-Specific"
         },
         {
-          "id":"1d1d1d1d1d1d11",
+          "id":"BBSIMOLT000",
           "hardwareIdentifier":"00:1b:22:00:b1:78",
           "ipAddress":"192.168.1.252",
-          "nasId":"B100-NASID"
+          "uplinkPort":65536,
+          "nasId":"BBSIMOLT000"
         },
         {  
           "id":"olt0.voltha.svc:50060",
           "uplinkPort":2
-        },
-        {
-          "id":"BBSIMOLT000",
-          "uplinkPort":65536
         }
       ]
     },
diff --git a/tests/atests/common/auto_test.py b/tests/atests/common/auto_test.py
index be52134..d2c5f7d 100755
--- a/tests/atests/common/auto_test.py
+++ b/tests/atests/common/auto_test.py
@@ -117,7 +117,7 @@
 
     authentication.run_test(ONU_COUNT, ROOT_DIR, VOLTHA_DIR, LOG_DIR, args.simtype)
 
-    if args.simtype == 'ponsim':
-        dhcp.run_test(ROOT_DIR, VOLTHA_DIR, LOG_DIR)
+    dhcp.run_test(ONU_COUNT, ROOT_DIR, VOLTHA_DIR, LOG_DIR, args.simtype)
 
+    if args.simtype == 'ponsim':
         unicast.run_test(ONU_TYPE, ONU_COUNT, ROOT_DIR, VOLTHA_DIR, LOG_DIR)
diff --git a/tests/atests/common/dhcp.py b/tests/atests/common/dhcp.py
index 391c2dc..9647ba6 100644
--- a/tests/atests/common/dhcp.py
+++ b/tests/atests/common/dhcp.py
@@ -41,6 +41,7 @@
         self.dirs['voltha'] = None
 
         self.__rgName = testCaseUtils.discover_rg_pod_name()
+        self.__onuCount = None
         self.__fields = None
         self.__deviceId = None
         self.__portNumber = None
@@ -48,25 +49,20 @@
     def h_set_log_dirs(self, root_dir, voltha_dir, log_dir):
         testCaseUtils.config_dirs(self, log_dir, root_dir, voltha_dir)
 
+    def h_configure(self, onu_count):
+        self.__onuCount = onu_count
+
     def discover_authorized_users(self):
         testCaseUtils.send_command_to_onos_cli(testCaseUtils.get_dir(self, 'log'),
                                                'voltha_onos_users.log', 'aaa-users')
 
-    def retrieve_authorized_users_device_id_and_port_number(self):
+    def extract_authorized_user_device_id_and_port_number(self):
         statusLines = testCaseUtils.get_fields_from_grep_command(self, 'AUTHORIZED', 'voltha_onos_users.log')
-        assert statusLines, 'No Users Authorized'
-        self.__fields = testCaseUtils.parse_fields(statusLines, ',')
-        deviceField = self.__fields[2].strip()
-        deviceStr, equal, deviceId = deviceField.partition('=')
-        self.__deviceId = deviceId
-        portField = self.__fields[4].strip()
-        portNumStr, equal, portNum = portField.partition('=')
-        self.__portNumber = portNum
+        assert statusLines, 'No ONU has been authenticated'
+        self.__deviceId, self.__portNumber = testCaseUtils.retrieve_authorized_users_device_id_and_port_number(statusLines)
 
-    def add_subscriber_access(self):
-        testCaseUtils.send_command_to_onos_cli(testCaseUtils.get_dir(self, 'log'),
-                                               'voltha_add_subscriber_access.log', 'volt-add-subscriber-access %s %s'
-                                               % (self.__deviceId, self.__portNumber))
+    def add_onu_bound_dhcp_flows(self):
+        testCaseUtils.add_subscriber_access(self, self.__deviceId, self.__portNumber)
 
     def should_now_have_two_dhcp_flows(self):
         testCaseUtils.send_command_to_onos_cli(testCaseUtils.get_dir(self, 'log'),
@@ -206,25 +202,42 @@
         statusLines = testCaseUtils.get_fields_from_grep_command(self, 'inet', self.CHECK_ASSIGNED_IP_FILENAME)
         assert statusLines, 'DHCP IP addr not assigned'
 
+    def should_have_ips_assigned_to_all_onus(self):
+        logging.info('Verifying IP Address assignment on all ONUs')
+        testCaseUtils.send_command_to_onos_cli(testCaseUtils.get_dir(self, 'log'),
+                                               '_voltha_onos_dhcpl2relay_allocations.log', 'dhcpl2relay-allocations')
+        statusLines = testCaseUtils.get_fields_from_grep_command(self, 'DHCPACK', '_voltha_onos_dhcpl2relay_allocations.log')
+        assert statusLines, 'No DHCP addresses allocated'
+        lines = statusLines.splitlines()
+        assert len(lines) == self.__onuCount, 'Allocated IPs does not match ONU count but result was %s' % len(lines)
+        for line in lines:
+            self.__fields = testCaseUtils.parse_fields(line, ',')
+            allocIp = self.__fields[5].strip()
+            allocated, delimiter, ipAddr = allocIp.partition('=')
+            assert ipAddr != '0.0.0.0', 'Invalid IP Address Allocated'
+
 
 def set_firewall_rules():
     logging.info('Setting Firewall rules for DHCP test')
     os.system('sudo iptables -P FORWARD ACCEPT')
 
 
-def run_test(root_dir, voltha_dir, log_dir):
-
-    set_firewall_rules()
+def run_test(onu_count, root_dir, voltha_dir, log_dir, simtype):
     dhcp = DHCP()
     dhcp.h_set_log_dirs(root_dir, voltha_dir, log_dir)
-    dhcp.discover_authorized_users()
-    dhcp.retrieve_authorized_users_device_id_and_port_number()
-    dhcp.add_subscriber_access()
-    dhcp.should_now_have_two_dhcp_flows()
-    dhcp.deactivate_dhcp_server_in_onos()
-    dhcp.add_dhcp_server_configuration_data_in_onos()
-    dhcp.activate_dhcp_server_in_onos()
-    dhcp.query_for_default_ip_on_rg()
-    dhcp.de_assign_default_ip_on_rg()
-    dhcp.assign_dhcp_ip_addr_to_rg()
-    dhcp.should_have_dhcp_assigned_ip()
+    dhcp.h_configure(onu_count)
+    if simtype == 'ponsim':
+        set_firewall_rules()
+        dhcp.discover_authorized_users()
+        dhcp.extract_authorized_user_device_id_and_port_number()
+        dhcp.add_onu_bound_dhcp_flows()
+        dhcp.should_now_have_two_dhcp_flows()
+        dhcp.deactivate_dhcp_server_in_onos()
+        dhcp.add_dhcp_server_configuration_data_in_onos()
+        dhcp.activate_dhcp_server_in_onos()
+        dhcp.query_for_default_ip_on_rg()
+        dhcp.de_assign_default_ip_on_rg()
+        dhcp.assign_dhcp_ip_addr_to_rg()
+        dhcp.should_have_dhcp_assigned_ip()
+    elif simtype == 'bbsim':
+        dhcp.should_have_ips_assigned_to_all_onus()
diff --git a/tests/atests/common/preprovisioning.py b/tests/atests/common/preprovisioning.py
index 2b077c9..c0b7cc0 100755
--- a/tests/atests/common/preprovisioning.py
+++ b/tests/atests/common/preprovisioning.py
@@ -132,19 +132,25 @@
     def proceed(self):
         logging.info('Pre-provisioning hold')
         onuOnline = 0
-        portType = None
         if self.__oltType == 'ponsim_olt':
             portType = 'PON_OLT'
+            while onuOnline < self.__onuCount:
+                testCaseUtils.send_command_to_voltha_cli(testCaseUtils.get_dir(self, 'log'), 'voltha_olt_device.log', 'device ' +
+                                                         self.__oltDeviceId, 'voltha_olt_ports.log', 'ports')
+                statusLines = testCaseUtils.get_fields_from_grep_command(self, portType, 'voltha_olt_ports.log')
+                lines = statusLines.splitlines()
+                onuOnline = len(lines)
+                time.sleep(5)
+                logging.info('All ONUs now Online!')
         elif self.__oltType == 'openolt':
-            portType = 'ETHERNET_UNI'
-        while onuOnline < self.__onuCount:
-            testCaseUtils.send_command_to_voltha_cli(testCaseUtils.get_dir(self, 'log'), 'voltha_olt_device.log', 'device ' +
-                                                     self.__oltDeviceId, 'voltha_olt_ports.log', 'ports')
-            statusLines = testCaseUtils.get_fields_from_grep_command(self, portType, 'voltha_olt_ports.log')
-            lines = statusLines.splitlines()
-            onuOnline = len(lines)
-            time.sleep(5)
-        logging.info('All ONUs now Online!')
+            while onuOnline < self.__onuCount:
+                testCaseUtils.send_command_to_onos_cli(testCaseUtils.get_dir(self, 'log'),
+                                                       'voltha_onu_auth.log', 'aaa-users')
+                statusLines = testCaseUtils.get_fields_from_grep_command(self, 'AUTHORIZED', 'voltha_onu_auth.log')
+                lines = statusLines.splitlines()
+                onuOnline = len(lines)
+                time.sleep(5)
+            logging.info('All ONUs now AUTHORIZED')
 
 
 def run_test(olt_ip_address, olt_port, olt_type, onu_type, onu_count, log_dir):
@@ -157,7 +163,7 @@
     preprovisioning.check_olt_fields_before_enabling()
     preprovisioning.enable()
     preprovisioning.status_should_be_success_after_enable_command()
+    preprovisioning.proceed()
     preprovisioning.query_devices_after_enabling()
     preprovisioning.check_olt_fields_after_enabling()
     preprovisioning.check_onu_fields_after_enabling()
-    preprovisioning.proceed()
diff --git a/tests/atests/common/testCaseUtils.py b/tests/atests/common/testCaseUtils.py
index 9b9b67d..529d540 100755
--- a/tests/atests/common/testCaseUtils.py
+++ b/tests/atests/common/testCaseUtils.py
@@ -172,3 +172,20 @@
 
 def discover_rg_pod_name():
     return extract_pod_name('rg0').strip()
+
+
+def retrieve_authorized_users_device_id_and_port_number(status_line):
+    fields = parse_fields(status_line, ',')
+    deviceField = fields[2].strip()
+    deviceStr, equal, deviceId = deviceField.partition('=')
+    device_Id = deviceId
+    portField = fields[4].strip()
+    portNumStr, equal, portNum = portField.partition('=')
+    portNumber = portNum
+    return device_Id, portNumber
+
+
+def add_subscriber_access(self, device_id, port_number):
+    send_command_to_onos_cli(get_dir(self, 'log'),
+                             'voltha_add_subscriber_access.log', 'volt-add-subscriber-access %s %s'
+                             % (device_id, port_number))
diff --git a/tests/atests/common/volthaMngr.py b/tests/atests/common/volthaMngr.py
index 84e937f..d450494 100755
--- a/tests/atests/common/volthaMngr.py
+++ b/tests/atests/common/volthaMngr.py
@@ -90,6 +90,12 @@
         os.system('curl --user karaf:karaf -X POST -H "Content-Type: application/json" '
                   'http://localhost:30120/onos/v1/network/configuration/apps/ -d @%s/tests/atests/build/sadis_json'
                   % testCaseUtils.get_dir(self, 'voltha'))
+        logging.debug('curl --user karaf:karaf -X POST -H "Content-Type: application/json" '
+                      'http://localhost:30120/onos/v1/network/configuration/apps/ -d @%s/tests/atests/build/dhcpl2relay_json'
+                      % testCaseUtils.get_dir(self, 'voltha'))
+        os.system('curl --user karaf:karaf -X POST -H "Content-Type: application/json" '
+                  'http://localhost:30120/onos/v1/network/configuration/apps/ -d @%s/tests/atests/build/dhcpl2relay_json'
+                  % testCaseUtils.get_dir(self, 'voltha'))
 
     def collect_pod_logs(self):
         logging.info('Collect logs from all Pods')
diff --git a/tests/atests/robot/voltha_automated_test_suite.robot b/tests/atests/robot/voltha_automated_test_suite.robot
index c86193f..24e690d 100755
--- a/tests/atests/robot/voltha_automated_test_suite.robot
+++ b/tests/atests/robot/voltha_automated_test_suite.robot
@@ -96,27 +96,23 @@
     Run Keyword If      '${SIMTYPE}' == 'ponsim'      Ponsim Authentication Steps
     ...  ELSE IF        '${SIMTYPE}' == 'bbsim'       BBSim Authentication Verification Step
 
-Dhcp IP Address Assignment on RG
+Dhcp IP Address Assignment
     [Documentation]     DHCP assigned IP Address
+    ...                 In the case where the simtype is 'ponsim' we do the following:
     ...                 A DHCP server is configured and Activated on Onos. We need to change
     ...                 the Firewall rules so as to allow packets to flow between RG and OLT/ONU
     ...                 We also must add a second DHCP flow rule in onos in the direction from NNI
     ...                 by calling 'add subscriber access' on onos. We then deassign the default
     ...                 IP address granted to RG upon instantiating the RG pod. Finally we invoke
     ...                 'dhclient' on RG to request a DHCP IP address.
-    [Tags]              ponsim
+    ...                 In the case where the symtype is 'bbsim' we simply confirm that all ONUs
+    ...                 were assigned an IP address. This happens automatically once all ONUs have
+    ...                 been authenticated and the DHCP requests transition between the bbsim
+    ...                 dhclient, dhcp server via the dhcpl2relay
     H Set Log Dirs      ${ROOT_DIR}     ${VOLTHA_DIR}    ${LOG_DIR}
-    Set Firewall Rules
-    Discover Authorized Users
-    Retrieve Authorized Users Device Id And Port Number
-    Add Subscriber Access
-    Should Now Have Two Dhcp Flows
-    Add Dhcp Server Configuration Data In Onos
-    Activate Dhcp Server In Onos
-    Wait Until Keyword Succeeds  ${RETRY_TIMEOUT_60}    ${RETRY_INTERVAL_2}    Query For Default Ip On Rg
-    De Assign Default Ip On Rg
-    Wait Until Keyword Succeeds  ${RETRY_TIMEOUT_60}    ${RETRY_INTERVAL_2}    Assign Dhcp Ip Addr To Rg
-    Wait Until Keyword Succeeds  ${RETRY_TIMEOUT_60}    ${RETRY_INTERVAL_2}    Should Have Dhcp Assigned Ip
+    H Configure         ${ONU_COUNT}
+    Run Keyword If      '${SIMTYPE}' == 'ponsim'      Ponsim DHCP Steps
+    ...  ELSE IF        '${SIMTYPE}' == 'bbsim'       BBSim DHCP Verification Step
 
 Unicast flow setup ctag/stag assignment
     [Documentation]     Unicast ctag/stag assignment
@@ -184,8 +180,26 @@
     Wait Until Keyword Succeeds    ${RETRY_TIMEOUT_60}    ${RETRY_INTERVAL_2}    Should Have All Onus Authenticated
    
 Validate Number of Devices
-    [Documentation]    Validate the number of expected onus to be activated
+    [Documentation]     Validate the number of expected onus to be activated
     Query Devices After Enabling
     Status Should Be Success After Enable Command
     Check Olt Fields After Enabling
     Check Onu Fields After Enabling 
+
+Ponsim DHCP Steps
+    [Documentation]     List of steps required to run DHCP IP Address Assignment on RG
+    Set Firewall Rules
+    Discover Authorized Users
+    Extract Authorized User Device Id And Port Number
+    Add Onu Bound Dhcp Flows
+    Should Now Have Two Dhcp Flows
+    Add Dhcp Server Configuration Data In Onos
+    Activate Dhcp Server In Onos
+    Wait Until Keyword Succeeds  ${RETRY_TIMEOUT_60}    ${RETRY_INTERVAL_2}    Query For Default Ip On Rg
+    De Assign Default Ip On Rg
+    Wait Until Keyword Succeeds  ${RETRY_TIMEOUT_60}    ${RETRY_INTERVAL_2}    Assign Dhcp Ip Addr To Rg
+    Wait Until Keyword Succeeds  ${RETRY_TIMEOUT_60}    ${RETRY_INTERVAL_2}    Should Have Dhcp Assigned Ip
+
+BBSim DHCP Verification Step
+    [Documentation]     Validate that all ONUs were assigned an IP address
+    Wait Until Keyword Succeeds  ${RETRY_TIMEOUT_60}    ${RETRY_INTERVAL_2}     Should Have Ips Assigned To All Onus
\ No newline at end of file