*** Settings ***
Documentation     Test suite for Utility Synchronizer API
Suite Setup       Suite Setup
Suite Teardown    Suite Teardown
Variables         ../Framework/restApi.py
Library           Collections
Library           String
Library           OperatingSystem
Library           XML
Library           RequestsLibrary
Library           ../Framework/utils/utils.py
Library           ../Framework/restApi.py
Variables         ../Properties/RestApiProperties.py
Resource           ../Framework/utils/utils.robot

*** Variables ***
${VM_USER}            admin
${VM_PASS}            admin
${SSH_KEY}            id_rsa.pub
${ONOS_CORDVTN_API}   http://onos-cord:8182/onos/cordvtn

*** Test Cases ***
Get Compute Node Hostname + IP
    [Documentation]    Logs into ciab server and executes a 'cord prov list' on the headnode to get the compute node
    [Tags]    computenode
    ${compute_node_hostname}=    Execute Command on CIAB Server in Specific VM    ${SERVER_IP}    prod    cord prov list | grep node | awk '{print $2}'
    ${compute_node_ip}=    Execute Command on CIAB Server in Specific VM    ${SERVER_IP}    prod    cord prov list | grep node | awk '{print $4}'
    Set Suite Variable    ${compute_node_hostname}
    set suite variable    ${compute_node_ip}

Get ONOSCORD Container ID
    [Documentation]    Logs into ciab server and extracts the onoscord container id on the headnode
    [Tags]    onoscord
    ${onoscord_id}=    Get Docker Container ID    ${SERVER_IP}    onoscord    ${VM_USER}    ${VM_PASS}

Validate Default OVS Flow Count
    [Documentation]    Logs into the compute-node where OVS is running and validates the default flow count
    [Tags]    ovsflows
    ${ovs_flow_count}=    Execute Command on Compute Node in CIAB    ${SERVER_IP}    ${compute_node_hostname}    ovs-ofctl dump-flows br-int | wc -l
    ${ovs_flow_count}=    Get Line    ${ovs_flow_count}    0
    Should Be Equal As Integers    ${ovs_flow_count}    42

Validate Default Flow Count in ONOS
    [Documentation]    Validates the number of flows pushed down by onos (should match number flow count in ovs)
    [Tags]    onosflows    notready
    Log    Validating ONOS Flow Count

Validate Current VTN Service Networks and Ports
    [Documentation]    Makes rest calls to both XOS and ONOSCORD to validate the default VTN Service Networks + Ports
    [Tags]    vtnservice
    Validate Default CIAB Service Networks and Ports via XOS
    ${serviceNetworks}=    Execute Command on CIAB Server in Specific VM    ${SERVER_IP}    prod    curl -X GET -u karaf:karaf -H "Content-Type: application/json" http://onos-cord:8182/onos/cordvtn/serviceNetworks; echo
    Validate Default CIAB Service Networks via ONOSCORD    ${serviceNetworks}
    ${servicePorts}=    Execute Command on CIAB Server in Specific VM    ${SERVER_IP}    prod    curl -X GET -u karaf:karaf -H "Content-Type: application/json" http://onos-cord:8182/onos/cordvtn/servicePorts; echo
    Validate Default CIAB Service Ports via ONOSCORD    ${servicePorts}

Create New VTN Service Network
    [Documentation]    Makes a POST Request from the head-node to the ONOS Cord-VTN App to create a new service network
    [Tags]    vtnservice
    ${network_uuid}=    Generate UUID
    Set Suite Variable    ${network_uuid}
    ${networkCreation}=    Execute Command on CIAB Server in Specific VM    ${SERVER_IP}    prod    curl -s -o /dev/null -w "\%{http_code}" -X POST -u karaf:karaf -H "Content-Type: application/json" -d '{"ServiceNetwork": {"id": "${network_uuid}", "type": "PRIVATE", "name": "APITEST", "segment_id": 2221, "subnet": "2.2.2.0/24", "service_ip": "2.2.2.1", "providers": [{"id": "${public_network_id}", "bidirectional": true}]}}' http://onos-cord:8182/onos/cordvtn/serviceNetworks; echo
    Should Be Equal As Integers    ${networkCreation}    201
    ${new_network}=    Execute Command on CIAB Server in Specific VM    ${SERVER_IP}    prod    curl -X GET -u karaf:karaf -H "Content-Type: application/json" http://onos-cord:8182/onos/cordvtn/serviceNetworks/${network_uuid}; echo
    Log    ${new_network}
    ${name}=    Get Json Value    ${new_network}    /ServiceNetwork/name
    ${type}=    Get Json Value    ${new_network}    /ServiceNetwork/type
    ${segment_id}=    Get Json Value    ${new_network}    /ServiceNetwork/segment_id
    ${subnet}=    Get Json Value    ${new_network}    /ServiceNetwork/subnet
    ${service_ip}=    Get Json Value    ${new_network}    /ServiceNetwork/service_ip
    Should Be Equal As Strings    ${name}    "APITEST"
    Should Be Equal As Strings    ${type}    "PRIVATE"
    Should Be Equal As Strings    ${segment_id}    2221
    Should Be Equal As Strings    ${subnet}    "2.2.2.0/24"
    Should Be Equal As Strings    ${service_ip}    "2.2.2.1"

Create New VTN Service Port
    [Documentation]    Makes a POST Request from the head-node to the ONOS Cord-VTN App to create a new service port for the newly created network
    [Tags]    vtnservice
    ${port_uuid}=    Generate UUID
    Set Suite Variable    ${port_uuid}
    ${networkCreation}=    Execute Command on CIAB Server in Specific VM    ${SERVER_IP}    prod    curl -s -o /dev/null -w "\%{http_code}" -X POST -u karaf:karaf -H "Content-Type: application/json" -d '{"ServicePort": {"id": "${port_uuid}", "network_id": "${network_uuid}", "name": "APITESTPORT", "mac_address": "FA:16:3E:A8:A1:AA", "ip_address": "2.2.2.1", "floating_address_pairs":[{"ip_address":"3.3.3.1","mac_address":"02:42:0A:06:01:11"}]}}' http://onos-cord:8182/onos/cordvtn/servicePorts; echo
    Should Be Equal As Integers    ${networkCreation}    201
    ${new_port}=    Execute Command on CIAB Server in Specific VM    ${SERVER_IP}    prod    curl -X GET -u karaf:karaf -H "Content-Type: application/json" http://onos-cord:8182/onos/cordvtn/servicePorts/${port_uuid}; echo
    Log    ${new_port}
    ${name}=    Get Json Value    ${new_port}    /ServicePort/name
    ${netId}=    Get Json Value    ${new_port}    /ServicePort/network_id
    ${mac_address}=    Get Json Value    ${new_port}    /ServicePort/mac_address
    ${ip_address}=    Get Json Value    ${new_port}    /ServicePort/ip_address
    ${floating_pairs}=    Get Json Value    ${new_port}    /ServicePort/floating_address_pairs
    Should Be Equal As Strings    ${name}    "APITESTPORT"
    Should Be Equal As Strings    ${netId}    "${network_uuid}"
    Should Be Equal As Strings    ${mac_address}    "FA:16:3E:A8:A1:AA"
    Should Be Equal As Strings    ${ip_address}    "2.2.2.1"

Validate New Flows Pushed to OVS
    [Documentation]    Logs into the compute-node where OVS is running and validates the default flow count
    [Tags]    vtnservice
    ${ovs_flow_count}=    Execute Command on Compute Node in CIAB    ${SERVER_IP}    ${compute_node_hostname}    ovs-ofctl dump-flows br-int | grep 2.2.2.0 | wc -l
    ${ovs_flow_count}=    Get Line    ${ovs_flow_count}    0
    Should Be Equal As Integers    ${ovs_flow_count}    3
    ${flows_added}=    Execute Command on Compute Node in CIAB    ${SERVER_IP}    ${compute_node_hostname}    ovs-ofctl dump-flows br-int
    ${flows_added}=    Get Lines Containing String    ${flows_added}    cookie=
    Log    ${flows_added}
    ## Match src/dst (bi-directional) rules on new flows added
    Should Contain    ${flows_added}    nw_src=2.2.2.0/24,nw_dst=10.6.1.192/26
    Should Contain    ${flows_added}    nw_src=10.6.1.192/26,nw_dst=2.2.2.0/24
    Should Contain    ${flows_added}    nw_src=2.2.2.0/24,nw_dst=10.6.1.193

Delete VTN Service Port
    [Documentation]    Makes a DELETE Request from the head-node to the ONOS Cord-VTN App to delete the new service port
    [Tags]    vtnservice
    ${networkDeletion}=    Execute Command on CIAB Server in Specific VM    ${SERVER_IP}    prod    curl -s -o /dev/null -w "\%{http_code}" -X DELETE -u karaf:karaf -H "Content-Type: application/json" http://onos-cord:8182/onos/cordvtn/servicePorts/${port_uuid}; echo
    Should Be Equal As Integers    ${networkDeletion}    204
    ${get_port}=    Execute Command on CIAB Server in Specific VM    ${SERVER_IP}    prod    curl -s -o /dev/null -w "\%{http_code}" -X GET -u karaf:karaf -H "Content-Type: application/json" http://onos-cord:8182/onos/cordvtn/servicePorts/${port_uuid}; echo
    Should Be Equal As Integers    ${get_port}    404

Delete VTN Service Network
    [Documentation]    Makes a DELETE Request from the head-node to the ONOS Cord-VTN App to delete the created service network
    [Tags]    vtnservice
    ${networkDeletion}=    Execute Command on CIAB Server in Specific VM    ${SERVER_IP}    prod    curl -s -o /dev/null -w "\%{http_code}" -X DELETE -u karaf:karaf -H "Content-Type: application/json" http://onos-cord:8182/onos/cordvtn/serviceNetworks/${network_uuid}; echo
    Should Be Equal As Integers    ${networkDeletion}    204
    ${get_network}=    Execute Command on CIAB Server in Specific VM    ${SERVER_IP}    prod    curl -s -o /dev/null -w "\%{http_code}" -X GET -u karaf:karaf -H "Content-Type: application/json" http://onos-cord:8182/onos/cordvtn/serviceNetworks/${network_uuid}; echo
    Should Be Equal As Integers    ${get_network}    404

Validate New Flows Removed From OVS
    [Documentation]    Validates that the flow rules added by ONOS from the network creation has been removed
    [Tags]    vtnservice
    ${ovs_flow_count}=    Execute Command on Compute Node in CIAB    ${SERVER_IP}    ${compute_node_hostname}    ovs-ofctl dump-flows br-int | grep 2.2.2.0 | wc -l
    ${ovs_flow_count}=    Get Line    ${ovs_flow_count}    0
    Should Be Equal As Integers    ${ovs_flow_count}    0
    ${flows_added}=    Execute Command on Compute Node in CIAB    ${SERVER_IP}    ${compute_node_hostname}    ovs-ofctl dump-flows br-int
    ${flows_added}=    Get Lines Containing String    ${flows_added}    cookie=
    Log    ${flows_added}
    ## Validate flow rules arent in the flows table
    Should Not Contain    ${flows_added}    nw_src=2.2.2.0/24,nw_dst=10.6.1.192/26
    Should Not Contain    ${flows_added}    nw_src=10.6.1.192/26,nw_dst=2.2.2.0/24
    Should Not Contain    ${flows_added}    nw_src=2.2.2.0/24,nw_dst=10.6.1.193

*** Keywords ***
Suite Setup
    ${auth} =    Create List    ${USER}    ${PASSWD}
    Create Session    ${SERVER_IP}    http://${SERVER_IP}:${SERVER_PORT}    auth=${AUTH}

Suite Teardown
    Delete All Sessions
    Close All Connections

CORD Get
    [Documentation]    Make a rest call to the CORD controller
    [Arguments]    ${session}    ${service}
    ${resp}=    Get Request    ${session}    ${service}
    Log    ${resp.content}
    [Return]    ${resp}

Validate Default CIAB Service Networks and Ports via XOS
    [Documentation]    Using XOS API, this validates the default VTN Service Networks + Ports for a CIAB Environment
    @{expected_types}=    Create List    PUBLIC    PRIVATE    MANAGEMENT_LOCAL    VSG
    @{expected_owner_slices}=    Create List    mysite_public    mysite_exampleservice    mysite_management    mysite_vsg
    @{expected_network_names}=    Create List    public    management    exampleservice_network    mysite_vsg-access
    @{types}=    Create List
    @{ownerSlices}=    Create List
    @{network_names}=    Create List
    ${resp}=    CORD GET    ${SERVER_IP}    /api/service/vtn/serviceNetworks/
    Should Be Equal As Strings    ${resp.status_code}    200
    ${jsondata}=    To Json    ${resp.content}
    ${length}=    Get Length    ${jsondata['serviceNetworks']}
    Should Be Equal As Integers    ${length}    4
    : FOR    ${INDEX}    IN RANGE    0    ${length}
    \    ${item}=    Get From List    ${jsondata['serviceNetworks']}    ${INDEX}
    \    ${type}=    Get From Dictionary    ${item}    type
    \    ${ownerSliceName}=    Get From Dictionary    ${item}    ownerSliceName
    \    Append To List    ${types}    ${type}
    \    Append To List    ${ownerSlices}    ${ownerSliceName}
    : FOR    ${value}    IN    @{expected_types}
    \    List Should Contain Value    ${types}    ${value}
    : FOR    ${value}    IN    @{expected_owner_slices}
    \    List Should Contain Value    ${ownerSlices}    ${value}
    ${resp}=    CORD GET    ${SERVER_IP}    /api/service/vtn/servicePorts/
    Should Be Equal As Strings    ${resp.status_code}    200
    ${jsondata}=    To Json    ${resp.content}
    ${length}=    Get Length    ${jsondata['servicePorts']}
    Should Be Equal As Integers    ${length}    5
    : FOR    ${INDEX}    IN RANGE    0    ${length}
    \    ${item}=    Get From List    ${jsondata['servicePorts']}    ${INDEX}
    \    ${network_name}=    Get From Dictionary    ${item}    network_name
    \    Append To List    ${network_names}    ${network_name}
    : FOR    ${value}    IN    @{expected_network_names}
    \    List Should Contain Value    ${network_names}    ${value}
    ${management_len}=    Count Values in List    ${network_names}    management
    Should Be Equal As Integers    ${management_len}    2

Validate Default CIAB Service Networks via ONOSCORD
    [Documentation]    Validates the default VTN Service Network via ONOSCORD for a CIAB Environment
    [Arguments]    ${jsondata}
    @{network_ids}=    Create List
    @{expected_types}=    Create List    PUBLIC    PRIVATE    MANAGEMENT_LOCAL    VSG
    @{expected_names}=    Create List    public    exampleservice_network    management    mysite_vsg-access
    @{types}=    Create List
    @{names}=    Create List
    ${jsondata}=    To Json    ${jsondata}
    ${length}=    Get Length    ${jsondata['ServiceNetworks']}
    Should Be Equal As Integers    ${length}    4
    : FOR    ${INDEX}    IN RANGE    0    ${length}
    \    ${item}=    Get From List    ${jsondata['ServiceNetworks']}    ${INDEX}
    \    ${network_id}=    Get From Dictionary    ${item}    id
    \    ${type}=    Get From Dictionary    ${item}    type
    \    ${name}=    Get From Dictionary    ${item}    name
    \    Append To List    ${network_ids}    ${network_id}
    \    Append To List    ${types}    ${type}
    \    Append To List    ${names}    ${name}
    \    Run Keyword If    "${name}" == "management"    Set Suite Variable    ${management_network_id}    ${network_id}
    \    Run Keyword If    "${name}" == "public"    Set Suite Variable    ${public_network_id}    ${network_id}
    : FOR    ${value}    IN    @{expected_types}
    \    List Should Contain Value    ${types}    ${value}
    : FOR    ${value}    IN    @{expected_names}
    \    List Should Contain Value    ${names}    ${value}
    Set Suite Variable    ${network_ids}

Validate Default CIAB Service Ports via ONOSCORD
    [Documentation]    Validates the default VTN Service Ports via ONOSCORD for a CIAB Environment
    [Arguments]    ${jsondata}
    ${net_ids}=    Create List
    ${jsondata}=    To Json    ${jsondata}
    ${length}=    Get Length    ${jsondata['ServicePorts']}
    Should Be Equal As Integers    ${length}    5
    : FOR    ${INDEX}    IN RANGE    0    ${length}
    \    ${item}=    Get From List    ${jsondata['ServicePorts']}    ${INDEX}
    \    ${net_id}=    Get From Dictionary    ${item}    network_id
    \    Append To List    ${net_ids}    ${net_id}
    : FOR    ${value}    IN    @{net_ids}
    \    List Should Contain Value    ${network_ids}    ${value}
    ${management_len}=    Count Values in List    ${net_ids}    ${management_network_id}
    Should Be Equal As Integers    ${management_len}    2
