# Copyright 2017-present Open Networking Foundation
#
# 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.

*** Settings ***
Documentation     Test successful ping from end-end
Suite Setup       Setup
Suite Teardown    Teardown
Test Setup        Create Models
Test Teardown     Clean Test Environment
Library           Collections
Library           String
Library           OperatingSystem
Library           XML
Library           RequestsLibrary
Library           ../../Framework/utils/utils.py
Resource          ../../Framework/utils/utils.robot
Library           ../../Framework/restApi.py
Resource          ../../Framework/Subscriber.robot
Resource          ../../Framework/ATTWorkFlowDriver.robot
Resource          ../../Framework/Kubernetes.robot
Resource          ../../Framework/ONU.robot
Resource          ../../Framework/OLT.robot
Resource          ../../Framework/DHCP.robot
Variables         ../../Properties/RestApiProperties.py

*** Variables ***
${WHITELIST_PATHFILE}     ${CURDIR}/data/ATTWhiteList.json
${SUBSCRIBER_PATHFILE}    ${CURDIR}/data/ATTSubscriber.json
${VOLT_DEVICE_PATHFILE}    ${CURDIR}/../data/RealOLTDevice.json
${src_ip}          X.X.X.X
${src_gateway}     X.X.X.X
${src_user}        user
${src_pass}        ${EMPTY}
${src_key}         ${EMPTY}
${src_container_name}         ${EMPTY}
${src_iface}       eth0
${dst_ip}          ${EMPTY}
${dst_dp_iface}    eth0
${dst_dp_ip}       X.X.X.X
${dst_user}        user
${dst_pass}        ${EMPTY}
${dst_key}         ${EMPTY}
${dst_container_name}         ${EMPTY}
${dst_gateway}     X.X.X.X
${olt_ip}          X.X.X.X
${olt_user}          user
${olt_pass}          ${EMPTY}
${kubernetes_conf}    x.conf
${kubernetes_yml}    x.yml
${helm_dir}    ~/helm-charts
${voltha_pod_num}    8

*** Test Cases ***
ONU in Correct Location + Successful Auth Request
    [Documentation]    Validates E2E Ping Connectivity and object states for the given scenario:
    ...    Discovery of ONU Device after whitelist has been configured
    ...    Sending of a successful 802.1x auth request
    ...    Configuration of the destination servers interface and start dhcpd
    ...    Configuration of source server interface and execute dhclient on interface
    ...    Validate successful pings from src to dst
    [Setup]    None
    Wait Until Keyword Succeeds    300s    15s    Validate ONU States    ACTIVE    ENABLED
    Wait Until Keyword Succeeds    60s    2s    Validate ATT Workflow Driver SI    ENABLED    AWAITING
    Wait Until Keyword Succeeds    60s    2s    Validate Subscriber Status    awaiting-auth
    Send EAPOL Message    True    ${src_iface}    wpa_supplicant.conf    ${src_ip}    ${src_user}    ${src_pass}    ${src_key}    ${src_container_name}
    Wait Until Keyword Succeeds    60s    2s    Validate ATT Workflow Driver SI    ENABLED    APPROVED
    Wait Until Keyword Succeeds    60s    2s    Validate Subscriber Status    enabled
    Validate DHCP and Ping    True    True

ONU in Correct Location + Skip Auth
    [Documentation]    Validates E2E Ping Connectivity and object states for the given scenario:
    ...    Discovery of ONU Device after whitelist has been configured
    ...    Configuration of the destination servers interface and start dhcpd
    ...    Configuration of source server interface and execute dhclient on interface
    ...    Validate failed DHCP and pings from src to dst
    Wait Until Keyword Succeeds    300s    15s    Validate ONU States    ACTIVE    ENABLED
    Wait Until Keyword Succeeds    60s    2s    Validate ATT Workflow Driver SI    ENABLED    AWAITING
    Wait Until Keyword Succeeds    60s    2s    Validate Subscriber Status    awaiting-auth
    Validate DHCP and Ping    False    False

ONU not in Whitelist + Failed Auth Request
    [Documentation]    Validates E2E Ping Connectivity and object states for the given scenario:
    ...    Discovery of ONU Device that is not in the whitelist
    ...    Sending a 802.1x auth request
    ...    Configuration of the destination servers interface and start dhcpd
    ...    Configuration of source server interface and execute dhclient on interface
    ...    Validate failed DHCP and pings from src to dst
    [Setup]    None
    ${SubscriberList} =    Get Variable Value    ${slist}
    ${SubscriberDict}=    utils.listToDict    ${SubscriberList}    0
    Wait Until Keyword Succeeds    120s    15s    CORD Post    ${VOLT_SUBSCRIBER}    ${SubscriberDict}
    ${VoltDeviceList} =    Get Variable Value    ${vlist}
    ${VoltDeviceDict}=    utils.listToDict    ${VoltDeviceList}    0
    CORD Post    ${VOLT_DEVICE}    ${VoltDeviceDict}
    Wait Until Keyword Succeeds    300s    15s    Validate ONU States    UNKNOWN    DISABLED
    Wait Until Keyword Succeeds    60s    2s    Validate ATT Workflow Driver SI    DISABLED    AWAITING
    Wait Until Keyword Succeeds    60s    2s    Validate Subscriber Status    awaiting-auth
    Send EAPOL Message    False    ${src_iface}    wpa_supplicant.conf    ${src_ip}    ${src_user}    ${src_pass}    ${src_key}    ${src_container_name}
    Wait Until Keyword Succeeds    60s    2s    Validate ATT Workflow Driver SI    DISABLED    AWAITING
    Wait Until Keyword Succeeds    60s    2s    Validate Subscriber Status    awaiting-auth
    Validate DHCP and Ping    False    False

*** Keywords ***
Setup
    ${auth} =    Create List    ${XOS_USER}    ${XOS_PASSWD}
    ${HEADERS}    Create Dictionary    Content-Type=application/json
    Create Session    ${server_ip}    http://${server_ip}:${server_port}    auth=${AUTH}    headers=${HEADERS}
    ${att_workflow_service_id}=    Get Service Owner Id    ${ATT_SERVICE}
    ${volt_service_id}=    Get Service Owner Id    ${VOLT_SERVICE}
    ${AttWhiteListList}=    utils.jsonToList    ${WHITELIST_PATHFILE}   AttWhiteListInfo
    Set Suite Variable    ${alist}    ${AttWhiteListList}
    ${AttWhiteListList} =    Get Variable Value    ${alist}
    ${AttWhiteListDict}=    utils.listToDict    ${AttWhiteListList}    0
    ${AttWhiteListDict}=    utils.setFieldValueInDict    ${AttWhiteListDict}    owner_id    ${att_workflow_service_id}
    ${onu_device}=   Get From Dictionary    ${AttWhiteListDict}    serial_number
    Log    ${onu_device}
    Set Global Variable    ${onu_device}
    ${SubscriberList}=    utils.jsonToList    ${SUBSCRIBER_PATHFILE}   SubscriberInfo
    Set Global Variable    ${slist}    ${SubscriberList}
    ${SubscriberList} =    Get Variable Value    ${slist}
    ${SubscriberDict}=    utils.listToDict    ${SubscriberList}    0
    ${s_tag}=    utils.getFieldValueFromDict    ${SubscriberDict}   s_tag
    ${c_tag}=    utils.getFieldValueFromDict    ${SubscriberDict}   c_tag
    ${VoltDeviceList}=    utils.jsonToList    ${VOLT_DEVICE_PATHFILE}   VOLTDeviceInfo
    Set Global Variable    ${vlist}    ${VoltDeviceList}
    Set Suite Variable    ${s_tag}
    Set Suite Variable    ${c_tag}
    Set Global Variable    ${export_kubeconfig}    export KUBECONFIG=${kubernetes_conf}

Teardown
    [Documentation]    Performs any additional cleanup required
    Log    Suite Teardown cleanup
    Delete All Sessions

Create Models
    [Documentation]    Re-create Subscriber, whitelist, and olt-device models to test
    Log    Re-creating objects
    #create attwhitelist
    ${AttWhiteListList} =    Get Variable Value    ${alist}
    ${AttWhiteListDict}=    utils.listToDict    ${AttWhiteListList}    0
    CORD Post    ${ATT_WHITELIST}    ${AttWhiteListDict}
    #create subscriber
    ${SubscriberList} =    Get Variable Value    ${slist}
    ${SubscriberDict}=    utils.listToDict    ${SubscriberList}    0
    Wait Until Keyword Succeeds    120s    15s    CORD Post    ${VOLT_SUBSCRIBER}    ${SubscriberDict}
    #create olt device
    ${VoltDeviceList} =    Get Variable Value    ${vlist}
    ${VoltDeviceDict}=    utils.listToDict    ${VoltDeviceList}    0
    CORD Post    ${VOLT_DEVICE}    ${VoltDeviceDict}

Clean Test Environment
    [Documentation]    Delete xos objects, kills processes and cleans up interfaces on src+dst servers
    Run Keyword And Ignore Error    Kill Linux Process    [w]pa_supplicant    ${src_ip}    ${src_user}    ${src_pass}    ${src_key}    ${src_container_name}
    Run Keyword And Ignore Error    Kill Linux Process    [d]hclient    ${src_ip}    ${src_user}    ${src_pass}    ${src_key}    ${src_container_name}
    Run Keyword If    '${dst_ip}' != '${EMPTY}'    Run Keyword And Ignore Error    Kill Linux Process    [d]hcpd    ${dst_ip}    ${dst_user}    ${dst_pass}    ${dst_key}    ${dst_container_name}
    Delete IP Addresses from Interface on Remote Host    ${src_iface}    ${src_ip}    ${src_user}    ${src_pass}    ${src_key}    ${src_container_name}
    Run Keyword If    '${dst_ip}' != '${EMPTY}'    Delete Interface on Remote Host    ${dst_dp_iface}.${s_tag}    ${dst_ip}    ${dst_user}    ${dst_pass}    ${dst_key}    ${dst_container_name}
    Wait Until Keyword Succeeds    60s    2s    Clean Up Objects    ${VOLT_SUBSCRIBER}
    Wait Until Keyword Succeeds    60s    2s    Clean Up Objects    ${VOLT_DEVICE}
    Wait Until Keyword Succeeds    60s    2s    Clean Up Objects    ${ATT_WHITELIST}
    Wait Until Keyword Succeeds    120s    10s    Check Remote System Reachability    False    ${olt_ip}
    Wait Until Keyword Succeeds    120s    10s    Check Remote System Reachability    True    ${olt_ip}
    Wait Until Keyword Succeeds    120s    10s    Openolt is Up    ${olt_ip}    ${olt_user}    ${olt_pass}
    Wait Until Keyword Succeeds    300s    10s    Reinstall Voltha

Validate ONU States
    [Arguments]    ${expected_op_status}    ${expected_admin_status}
    ${operational_status}    ${admin_status}    ONU Status Check    ${onu_device}
    Should Be Equal    ${operational_status}    ${expected_op_status}
    Should Be Equal    ${admin_status}    ${expected_admin_status}

Validate ATT Workflow Driver SI
    [Arguments]    ${expected_status}    ${expected_auth_status}
    ${onu_state}   ${authentication_status}   Service Instance Status Check    ${onu_device}
    Should Be Equal    ${onu_state}    ${expected_status}
    Should Be Equal    ${authentication_status}    ${expected_auth_status}

Validate Subscriber Status
    [Arguments]    ${exepected_status}
    ${status}    Subscriber Status Check    ${onu_device}
    Should Be Equal    ${status}    ${exepected_status}

Validate DHCP and Ping
    [Arguments]    ${dhcp_should_pass}    ${ping_should_pass}
    Run Keyword If    '${dst_ip}' != '${EMPTY}'    Run Keywords
    ...    Add Double Vlan Interface on Host    ${dst_dp_iface}    ${s_tag}    ${c_tag}    ${dst_ip}    ${dst_user}    ${dst_pass}    ${dst_key}    ${dst_container_name}    AND
    ...    Add IP Address on Interface on Host    ${dst_dp_ip}/24    ${dst_dp_iface}.${s_tag}.${c_tag}    ${dst_ip}    ${dst_user}    ${dst_pass}    ${dst_key}    ${dst_container_name}    AND
    ...    Start DHCP Server on Remote Host    ${dst_dp_iface}.${s_tag}.${c_tag}    ${dst_ip}    ${dst_user}    ${dst_pass}    ${dst_key}    ${dst_container_name}
    Send Dhclient Request    ${src_iface}    ${src_ip}    ${src_user}    ${src_pass}    ${src_key}    ${src_container_name}
    Run Keyword If    '${dhcp_should_pass}' == 'True'    Wait Until Keyword Succeeds    60s    5s    Check IPv4 Address on DHCP Client    True    ${src_iface}    ${src_ip}    ${src_user}    ${src_pass}    ${src_key}    ${src_container_name}
    Run Keyword If    '${dhcp_should_pass}' == 'False'    Sleep    10s
    Run Keyword If    '${dhcp_should_pass}' == 'False'    Check IPv4 Address on DHCP Client    False    ${src_iface}    ${src_ip}    ${src_user}    ${src_pass}    ${src_key}    ${src_container_name}
    Run Keyword If    '${ping_should_pass}' == 'True'    Wait Until Keyword Succeeds    60s    5s    Check Ping    True    ${dst_dp_ip}    ${src_iface}    ${src_ip}    ${src_user}    ${src_pass}    ${src_key}    ${src_container_name}
    ...                                          ELSE    Wait Until Keyword Succeeds    60s    5s    Check Ping    False    ${dst_dp_ip}    ${src_iface}    ${src_ip}    ${src_user}    ${src_pass}    ${src_key}    ${src_container_name}

Reinstall Voltha
    Run    ${export_kubeconfig}; helm delete --purge voltha
    Wait Until Keyword Succeeds    60s    10s    Helm Chart is Removed    voltha
    Wait Until Keyword Succeeds    120s    10s    Kubernetes PODs in Namespace are Removed    voltha
    ${rc}    ${output}=    Run And Return Rc And Output    ${export_kubeconfig}; helm install -n voltha -f ${kubernetes_yml} --set etcd-operator.customResources.createEtcdClusterCRD=false ${helm_dir}/voltha
    ${rc}    ${output}=    Run And Return Rc And Output    ${export_kubeconfig}; helm upgrade -f ${kubernetes_yml} --set etcd-operator.customResources.createEtcdClusterCRD=true voltha ${helm_dir}/voltha
    Wait Until Keyword Succeeds    60s    10s    Kubernetes PODs in Namespace are Running    voltha    ${voltha_pod_num}
    Sleep    10s
