aboutsummaryrefslogtreecommitdiffstats
path: root/ansible/library/fetch_url_and_verify.py
blob: 6c5c0a8c246446354972340fd399be0caf68e9cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/env python
# Copyright (c) 2017 Intel Corporation
#
# 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.

DOCUMENTATION = '''
---
module: fetch_url_and_verify
short_description: Fetch image and verify against a SHA256SUM URL
description:
    - Download a URL and check it against a remote SHA256SUMS file
options:
  url: Image URL
  image_dest: Image filename
  sha256_url: SHA256SUMS URL
  dest: python file mode (w, wb, a, ab)
  retries: fetch retries
'''


def main():
    module = AnsibleModule(
        argument_spec={
            'url': {'required': True, 'type': 'str'},
            'sha256url': {'required': True, 'type': 'str'},
            'dest': {'required': True, 'type': 'path'},
            'retries': {'required': False, 'type': 'int', 'default': 3},
        }
    )
    params = module.params
    url = params['url']
    dest = params['dest']
    sha256url = params['sha256url']
    retries = params['retries']

    image_dir, image_filename = os.path.split(dest)
    rc, stdout, stderr = module.run_command(['curl', '-sS', sha256url])
    if rc == 0 and stdout:
        sha256line = next(
            (l for l in stdout.splitlines() if image_filename in l), "")
    if not sha256line:
        module.fail_json(
            msg="Unable to find SHA256SUMS line for file {}".format(
                image_filename))
    rc = \
    module.run_command(['sha256sum', '-c'], data=sha256line, cwd=image_dir)[0]
    if rc == 0:
        sha256sum = sha256line.split()[0]
        module.exit_json(changed=False, dest=dest, url=url,
                         sha256sum=sha256sum)

    for retry in range(retries):
        curl_rc, stdout, stderr = module.run_command(
            ['curl', '-sS', '-o', dest, url], cwd=image_dir)
        if curl_rc == 0:
            sha256_rc, stdout, stderr = module.run_command(['sha256sum', '-c'],
                                                           data=sha256line,
                                                           cwd=image_dir)
            if sha256_rc == 0:
                module.exit_json(changed=True)

    module.fail_json(msg="Unable to download {}".format(url), stdout=stdout,
                     stderr=stderr)


# <<INCLUDE_ANSIBLE_MODULE_COMMON>>
from ansible.module_utils.basic import *  # noqa

if __name__ == '__main__':
    main()
3'>553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706
# Copyright 2018-19 Spirent Communications.
#
# 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.

# pylint: disable=R0904
# pylint: disable=R0902
# twenty-two is reasonable in this script

"""
VSPER docker-controller.
"""

import io
import time
import ast
import math

from concurrent import futures

import grpc
from proto import vsperf_pb2
from proto import vsperf_pb2_grpc
from utils import ssh

_ONE_DAY_IN_SECONDS = 60 * 60 * 24


# pylint: disable=too-few-public-methods,no-self-use
class PseudoFile(io.RawIOBase):
    """
    Handle ssh command output.
    """

    def write(self, chunk):
        """
        Write to file
        """
        if "error" in chunk:
            return
        with open("./output.txt", "w") as fref:
            fref.write(chunk)


class VsperfController(vsperf_pb2_grpc.ControllerServicer):
    """
    Main Controller Class
    """

    def __init__(self):
        """
        Initialization
        """
        self.client = None
        self.dut_check = None
        self.dut = None
        self.user = None
        self.pwd = None
        self.vsperf_conf = None
        self.tgen_client = None
        self.tgen_check = None
        self.tgen = None
        self.tgen_user = None
        self.tgenpwd = None
        self.tgen_conf = None
        self.scenario = None
        self.testcase = None
        self.tgen_ip_address = None
        self.testtype = None
        self.trex_conf = None
        self.trex_params = None
        self.conffile = None
        self.tests_run_check = None
        self.tgen_start_check = None
        # Default TGen is T-Rex
        self.trex_conffile = "trex_cfg.yml"
        self.collectd_conffile = "collectd.conf"
        self.test_upload_check = 0
        self.sanity_check_done_list = list()

    def setup(self):
        """
        Performs Setup of the client.
        """
        # Just connect to VM.
        self.client = ssh.SSH(host=self.dut, user=self.user,
                              password=self.pwd)
        self.client.wait()

    def upload_config(self):
        """
        Perform file upload.
        """
        # self.client._put_file_shell(self.conffile, '~/vsperf.conf')
        self.client.put_file(self.conffile, '~/{}'.format(self.conffile))
        print("No")

    def run_test(self):
        """
        Run test
        """
        # Sometimes hugepage store in /mnt/huge in order to free up the
        # hugepage removing this stored hugepage is necessory
        rmv_cmd = "cd /mnt/huge && echo {} | sudo -S rm -rf *".format(self.pwd)
        self.client.run(rmv_cmd, pty=True)
        cmd = "source ~/vsperfenv/bin/activate ; "
        #cmd = "scl enable python33 bash ; "
        cmd += "cd vswitchperf* && "
        cmd += "./vsperf "
        if self.vsperf_conf:
            cmd += "--conf-file ~/{} ".format(self.conffile)
            # cmd += self.conffile
        cmd += self.scenario
        with PseudoFile() as pref:
            self.client.run(cmd, stdout=pref, pty=True, timeout=0)

    def TestStatus(self, request, context):
        """
        Chechk for the test status after performing test
        """
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        if self.tests_run_check != 1:
            return vsperf_pb2.StatusReply(message="No test have ran yet. [!]")
        testtype_list = request.testtype.split(",")
        test_success = []
        test_failed = []
        testtype_list_len = len(testtype_list)
        for test in testtype_list:
            #latest_result_cmd = "find /tmp -mindepth 1 -type d -cmin -5 -printf '%f'"
            test_result_dir = str((self.client.\
                              execute("find /tmp -mindepth 1 -type d -cmin -5 -printf '%f'")[1]).\
                              split('find')[0])
            #test_date_cmd = "date +%F"
            test_date = str(self.client.execute("date +%F")[1]).replace("\n", "")
            if test_date in test_result_dir:
                testcase_check_cmd = "cd /tmp && cd `ls -t | grep results | head -{} | tail -1`".\
                                      format(testtype_list_len)
                testcase_check_cmd += " && find . -maxdepth 1 -name '*{}*'".\
                                        format(test)
                testcase_check_output = str(self.client.execute(testcase_check_cmd)[1]).\
                                        split('\n', 2)
                check = 0
                for i in testcase_check_output:
                    if (".csv" in i) or (".md" in i) or (".rst" in i):
                        check += 1
                if check == 3:
                    test_success.append(test)
                else:
                    test_failed.append(test)
                testtype_list_len -= 1
        if len(testtype_list) == len(test_success):
            return vsperf_pb2.StatusReply(message="All Test Successfully Completed on DUT-Host" \
                                          "\nResults... [OK]")
        if not test_success:
            return vsperf_pb2.StatusReply(
                message="All Test Failed on DUT-Host \nResults... [Failed]")
        return vsperf_pb2.StatusReply(message="Only {} Test failed   Results ... [Failed]\n"\
                "All other Test Successfully Completed on DUT-Host     Results... [OK] ".\
                format(test_failed))

    def HostConnect(self, request, context):
        """
        Handle host connectivity command from client
        """
        self.dut = request.ip
        self.user = request.uname
        self.pwd = request.pwd
        self.setup()
        check_cmd = "ls -l"
        self.dut_check = int(self.client.execute(check_cmd)[0])
        return vsperf_pb2.StatusReply(message="Successfully Connected")

    def save_chunks_to_file(self, chunks, filename):
        """
        Write the output to file
        """
        with open(filename, 'w+') as fref:
            fref.write(chunks)

    def UploadConfigFile(self, request, context):
        """
        Handle upload config-file command from client
        """
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        chunks = request.Content
        filename = request.Filename
        self.conffile = filename
        self.save_chunks_to_file(chunks, filename)
        # This is chechking if vsperf.conf already exist first remove that and
        # then upload the new file.
        check_test_config_cmd = "find ~/ -maxdepth 1 -name {}".format(filename)
        check_test_result = str(self.client.execute(check_test_config_cmd)[1])
        if "{}".format(filename) in check_test_result:
            self.client.run("rm -f {}".format(filename))
        self.upload_config()
        self.test_upload_check = 1
        print("Hello")
        return vsperf_pb2.UploadStatus(Message="Successfully Uploaded", Code=1)

    def StartTest(self, request, context):
        """
        Handle start-test command from client
        """
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        sanity_dict = {1:"Check installed VSPERF",
                       2:"Check Test Config's VNF path is available on DUT-Host",
                       3:"Check NIC PCIs is available on Traffic Generator",
                       4:"Check CPU allocation on DUT-Host",
                       5:"Check installed Collectd",
                       6:"Check Connection between DUT-Host and Traffic Generator Host"}
        sanity_dict_option_list = list(sanity_dict.keys())
        remaining_sanity = [item for item in sanity_dict_option_list if item not in \
                            self.sanity_check_done_list]
        if remaining_sanity:
            sanity_return_msg = ""
            for i_sanity in remaining_sanity:
                sanity_return_msg += sanity_dict[i_sanity] + "\n"
            return vsperf_pb2.StatusReply(message="The following sanity checks are either not"\
                    " performed yet or Does not satisfy test requirements" \
                    "\n{}".format(sanity_return_msg))
        if self.test_upload_check == 0:
            return vsperf_pb2.StatusReply(message="Test File is not uploaded yet [!] " \
                         "\nUpload Test Configuration File.")
        if self.tgen_start_check != 1:
            return vsperf_pb2.StatusReply(message="Traffic Generator has not started yet [!]")
        self.vsperf_conf = request.conffile
        self.testtype = request.testtype
        testtype_list = self.testtype.split(",")
        self.tests_run_check = 1
        for test in testtype_list:
            self.scenario = test
            self.run_test()
        return vsperf_pb2.StatusReply(message="Test Successfully Completed")

###### Traffic Generator Related functions ####
    def TGenHostConnect(self, request, context):
        """
        Connect to TGen-Node
        """
        self.tgen = request.ip
        self.tgen_user = request.uname
        self.tgenpwd = request.pwd
        self.tgen_setup()
        check_tgen_cmd = "ls"
        self.tgen_check = int(self.tgen_client.execute(check_tgen_cmd)[0])
        return vsperf_pb2.StatusReply(message="Successfully Connected")

    def tgen_setup(self):
        """
        Setup the T-Gen Client
        """
        # Just connect to VM.
        self.tgen_client = ssh.SSH(host=self.tgen, user=self.tgen_user,
                                   password=self.tgenpwd)
        self.tgen_client.wait()

    def StartBeats(self, request, context):
        """
        Start fileBeats on DUT
        """
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        run_cmd = "echo '{}' | sudo -S service filebeat start".format(self.pwd)
        #run_cmd = "sudo service filebeat start"
        self.client.run(run_cmd, pty=True)
        return vsperf_pb2.StatusReply(message="Beats are started on DUT-Host")

    def DUTvsperfTestAvailability(self, request, context):
        """
        Before running test we have to make sure there is no other test running
        """
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        vsperf_ava_cmd = "ps -ef | grep -v grep | grep ./vsperf | awk '{print $2}'"
        vsperf_ava_result = len((self.client.execute(vsperf_ava_cmd)[1]).split("\n"))
        if vsperf_ava_result == 1:
            return vsperf_pb2.StatusReply(message="DUT-Host is available for performing" \
                                                  " VSPERF Test\nYou can perform Test!")
        return vsperf_pb2.StatusReply(message="DUT-Host is busy right now, Wait for some time\n\
            Always Check availability before Running Test!")


###Clean-UP process related functions####


    def vsperf_remove(self):
        """
        Actual removal of the VSPERF
        """
        vsperf_rm_cmd = "echo '{}' | sudo -S rm -r ~/vswitchperf".format(
            self.pwd)
        self.client.run(vsperf_rm_cmd, pty=True)
        vsperfenv_rm_cmd = "echo '{}' | sudo -S rm -r -f ~/vsperfenv".format(
            self.pwd)
        self.client.run(vsperfenv_rm_cmd, pty=True)

    def remove_uploaded_config(self):
        """
        Remove all the uploaded test configuration file
        """
        vconfig_rm_cmd = "rm ~/{}".format(self.conffile)
        self.client.run(vconfig_rm_cmd, pty=True)

    def result_folder_remove(self):
        """
        Remove result folder on DUT
        """
        remove_cmd = "rm -r /tmp/*results*"
        self.client.run(remove_cmd, pty=True)

    def collectd_remove(self):
        """
        Remove collectd from DUT
        """
        collectd_dwn_rm_cmd = "echo '{}' | sudo -S rm -r -f ~/collectd".format(
            self.pwd)
        self.client.run(collectd_dwn_rm_cmd, pty=True)
        collectd_rm_cmd = "echo '{}' | sudo -S rm -r -f /opt/collectd".format(
            self.pwd)
        self.client.run(collectd_rm_cmd, pty=True)

    def RemoveVsperf(self, request, context):
        """
        Handle VSPERF removal command from client
        """
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        self.vsperf_remove()
        return vsperf_pb2.StatusReply(message="Successfully VSPERF Removed")

    def TerminateVsperf(self, request, context):
        """
        Terminate the VSPERF and kill processes
        """
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        stress_kill_cmd = "pkill stress"
        python3_kill_cmd = "pkill python3"
        qemu_kill_cmd = "killall -9 qemu-system-x86_64"
        self.client.send_command(stress_kill_cmd)
        self.client.send_command(python3_kill_cmd)
        self.client.send_command(qemu_kill_cmd)

        # sometimes qemu resists to terminate, so wait a bit and kill it again
        qemu_check_cmd = "pgrep qemu-system-x86_64"
        qemu_cmd_response = self.client.execute(qemu_check_cmd)[1]

        if qemu_cmd_response != '':
            time.sleep(5)
            self.client.send_command(qemu_kill_cmds)
            time.sleep(5)

        ovs_kill_cmd = "pkill ovs-vswitchd"
        ovsdb_kill_cmd = "pkill ovsdb-server"
        vppctl_kill_cmd = "pkill vppctl"
        vpp_kill_cmd = "pkill vpp"
        vpp_cmd = "pkill -9".format(self.pwd)

        self.client.send_command(ovs_kill_cmd)
        time.sleep(1)
        self.client.send_command(ovsdb_kill_cmd)
        time.sleep(1)
        self.client.send_command(vppctl_kill_cmd)
        time.sleep(1)
        self.client.send_command(vpp_kill_cmd)
        time.sleep(1)
        self.client.send_command(vpp_cmd)
        time.sleep(1)

        return vsperf_pb2.StatusReply(
            message="All the VSPERF related process terminated successfully")

    def RemoveResultFolder(self, request, context):
        """
        Handle result folder removal command from client
        """
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        self.result_folder_remove()
        return vsperf_pb2.StatusReply(
            message="Successfully VSPERF Results Removed")

    def RemoveUploadedConfig(self, request, context):
        """
        Handle all configuration file removal command from client
        """
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        if self.tgen_check != 0:
            return vsperf_pb2.StatusReply(message="TGen-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " TGen-Host.")
        if self.test_upload_check == 0:
            return vsperf_pb2.StatusReply(message="Test File is not uploaded yet [!] " \
                         "\nUpload Test Configuration File.")
        self.remove_uploaded_config()
        return vsperf_pb2.StatusReply(
            message="Successfully All Uploaded Config Files Removed")

    def RemoveCollectd(self, request, context):
        """
        Handle collectd removal command from client
        """
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        self.collectd_remove()
        return vsperf_pb2.StatusReply(
            message="Successfully Collectd Removed From DUT-Host")

    def RemoveEverything(self, request, context):
        """
        Handle of removing everything from DUT command from client
        """
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        if self.tgen_check != 0:
            return vsperf_pb2.StatusReply(message="TGen-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " TGen-Host.")
        self.vsperf_remove()
        self.result_folder_remove()
        self.remove_uploaded_config()
        self.collectd_remove()
        return vsperf_pb2.StatusReply(
            message="Successfully Everything Removed From DUT-Host")

    def StartTGen(self, request, context):
        """
        Handle start-Tgen command from client
        """
        if self.tgen_check != 0:
            return vsperf_pb2.StatusReply(message="TGen-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " TGen-Host.")
        self.trex_params = request.params
        run_cmd = "cd trex_2.37/scripts ; "
        run_cmd += "./t-rex-64 "
        run_cmd += self.trex_params
        self.tgen_client.send_command(run_cmd)
        self.tgen_start_check = 1
        return vsperf_pb2.StatusReply(message="T-Rex Successfully running...")

    def SanityCollectdCheck(self, request, context):
        """
        Check and verify collectd is able to run and start properly
        """
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        check_collectd_cmd = "find /opt -maxdepth 1 -name 'collectd'"
        check_test_result = str(self.client.execute(check_collectd_cmd)[1])
        if "collectd" in check_test_result:
            check_collectd_run_cmd = "echo {} | sudo -S service collectd start".format(self.pwd)
            self.client.run(check_collectd_run_cmd, pty=True)
            check_collectd_status_cmd = "ps aux | grep collectd"
            check_collectd_status = str(self.client.execute(check_collectd_status_cmd)[1])
            if "/sbin/collectd" in check_collectd_status:
                self.sanity_check_done_list.append(int(5))
                return vsperf_pb2.StatusReply(message="Collectd is working Fine")
            return vsperf_pb2.StatusReply(message="Collectd Fail to Start, \
                                                   Install correctly before running Test")
        return vsperf_pb2.StatusReply(message="Collectd is not installed yet.")

    def SanityVNFpath(self, request, context):
        """
        Check if VNF image available on the mention path in Test Config File
        """
        # fetch the VNF path we placed in vsperf.conf file
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        if self.test_upload_check == 0:
            return vsperf_pb2.StatusReply(message="Test File is not uploaded yet [!] " \
                         "\nUpload Test Configuration File.")
        vsperf_conf_path = 'cat ~/{} | grep "GUEST_IMAGE"'.format(self.conffile)
        vsperf_conf_read = self.client.execute(vsperf_conf_path)[1]
        vnf_image_path = vsperf_conf_read.split("'")[1]
        vnf_path_check_cmd = "find {}".format(vnf_image_path)
        vfn_path_check_result = str(self.client.execute(vnf_path_check_cmd)[1])
        if vnf_image_path in vfn_path_check_result:
            self.sanity_check_done_list.append(int(2))
            return vsperf_pb2.StatusReply(message="Test Configratuion file has Correct "\
                "VNF path information on DUT-Host.....[OK]")
        return vsperf_pb2.StatusReply(message='Test Configuration file has wrongly placed VNF '\
            'path information \n'\
            'VNF is not available on DUT-Host................................[Failed]\n ')

    def SanityVSPERFCheck(self, request, context):
        """
        We have to make sure that VSPERF install correctly
        """
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        vsperf_check_command = "source ~/vsperfenv/bin/activate ; cd vswitchperf* && "
        vsperf_check_command += "./vsperf --help"
        vsperf_check_cmd_result = str(self.client.execute(vsperf_check_command)[1])
        vsperf_verify_list = [
            'usage',
            'positional arguments',
            'optional arguments',
            'test selection options',
            'test behavior options']
        for idx, i in enumerate(vsperf_verify_list, start=1):
            if str(i) in vsperf_check_cmd_result:
                if idx < 5:
                    continue
                elif idx == 5:
                    self.sanity_check_done_list.append(int(1))
                    return vsperf_pb2.StatusReply(
                        message="VSPERF Installed Correctly and Working fine")
            return vsperf_pb2.StatusReply(message="VSPERF Does Not Installed Correctly ," \
                                          "INSTALL IT AGAIN..............[Critical]")
        return vsperf_pb2.StatusReply(message="VSPERF Does Not Installed Correctly ," \
                                      "INSTALL IT AGAIN..............[Critical]")

    def SanityNICCheck(self, request, context):
        """
        Check either NIC PCI ids are Correctly placed or not
        """
        if self.tgen_check != 0:
            return vsperf_pb2.StatusReply(message="TGen-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " TGen-Host.")
        trex_conf_path = "cat /etc/trex_cfg.yaml | grep interfaces"
        trex_conf_read = self.tgen_client.execute(trex_conf_path)[1]
        nic_pid_ids_list = [trex_conf_read.split("\"")[1], trex_conf_read.split("\"")[3]]
        trex_nic_pic_id_cmd = "lspci | egrep -i --color 'network|ethernet'"
        trex_nic_pic_id = str(self.tgen_client.execute(trex_nic_pic_id_cmd)[1]).split('\n')
        acheck = 0
        for k in trex_nic_pic_id:
            for j in nic_pid_ids_list:
                if j in k:
                    acheck += 1
                else:
                    pass
        if acheck == 2:
            self.sanity_check_done_list.append(int(3))
            return vsperf_pb2.StatusReply(message="Both the NIC PCI Ids are Correctly "\
                "configured on TGen-Host..............")
        return vsperf_pb2.StatusReply(message="You configured NIC PCI Ids Wrong in "\
                "TGen-Host............................[OK]\n")

    def SanityTgenConnDUTCheck(self, request, context):
        """
        We should confirm the DUT connectivity with the Tgen and Traffic Generator is working or not
        """
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        self.tgen_ip_address = request.ip
        tgen_connectivity_check_cmd = "ping {} -c 1".format(
            self.tgen_ip_address)
        tgen_connectivity_check_result = int(
            self.client.execute(tgen_connectivity_check_cmd)[0])
        if tgen_connectivity_check_result == 0:
            self.sanity_check_done_list.append(int(6))
            return vsperf_pb2.StatusReply(
                message="DUT-Host is successfully reachable to Traffic Generator......")
        return vsperf_pb2.StatusReply(message="DUT-Host is unsuccessful to reach the \
                                      Traffic Generator \nMake sure to establish connection \
                                      between DUT-Host and TGen-Host before running Test\
                                       ............... ")

    def variable_from_test_config(self, aparameter):
        """This function can be use to read any configuration paramter from vsperf.conf"""
        read_cmd = 'cat ~/{} | grep "{}"'.format(aparameter, self.conffile)
        read_cmd_output = str(self.client.execute(read_cmd)[1])
        print(read_cmd_output)
        if not read_cmd_output or '#' in read_cmd_output:
            return 0
        return read_cmd_output.split("=")[1].strip()

    def cpumask2coreids(self, mask):
        """conver mask to coreids"""
        intmask = int(mask, 16)
        i = 1
        coreids = []
        while i < intmask:
            if i & intmask:
                coreids.append(str(math.frexp(i)[1]-1))
            i = i << 1
        return coreids

    def cpu_allocation_check(self, list1, list2):
        """compare to cpu_map list"""
        if len(list1) >= len(list2):
            if all(elem in list1  for elem in list2):
                self.sanity_check_done_list.append(int(4))
                return vsperf_pb2.StatusReply(message="CPU allocation properly done on" \
                    " DUT-Host.................[OK]")
            return vsperf_pb2.StatusReply(message="CPU allocation not done properly on " \
                "DUT-Host............[Failed]")
        return vsperf_pb2.StatusReply(message="CPU allocation not done properly on" \
            " DUT-Host............[Failed]")

    def SanityCPUAllocationCheck(self, request, context):
        """
        check for cpu-allocation on DUT-Host
        """
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        if self.test_upload_check == 0:
            return vsperf_pb2.StatusReply(message="Test File is not uploaded yet [!] " \
                         "\nUpload Test Configuration File.")
        read_setting_cmd = "source vsperfenv/bin/activate ; cd vswitchperf* && "
        read_setting_cmd += './vsperf --list-settings'
        default_vsperf_settings = ast.literal_eval(str(self.client.execute(read_setting_cmd)[1]))
        default_cpu_map = default_vsperf_settings["VSWITCH_VHOST_CPU_MAP"]
        default_vswitch_pmd_cpu_mask = str(default_vsperf_settings["VSWITCH_PMD_CPU_MASK"])
        default_vswitch_vhost_cpu_map = [str(x) for x in default_cpu_map]
        vswitch_pmd_cpu_mask = self.variable_from_test_config("VSWITCH_PMD_CPU_MASK")
        vswitch_cpu_map = (self.variable_from_test_config("VSWITCH_VHOST_CPU_MAP"))
        vswitch_vhost_cpu_map = 0

        if vswitch_cpu_map != 0:
            vswitch_vhost_cpu_map = [str(x) for x in  ast.literal_eval(vswitch_cpu_map)]

        if vswitch_pmd_cpu_mask == 0 and vswitch_vhost_cpu_map == 0:
            self.sanity_check_done_list.append(int(4))
            return vsperf_pb2.StatusReply(message="CPU allocation Check Done,"\
                "\nNo vswitch_pmd_cpu_mask or vswitch_vhost_cpu_map assign in test " \
                "configuration file.\nUsing Default Settings..[OK]\n")
        if vswitch_pmd_cpu_mask != 0 and vswitch_vhost_cpu_map == 0:
            core_id = self.cpumask2coreids(vswitch_pmd_cpu_mask)
            return self.cpu_allocation_check(default_vswitch_vhost_cpu_map, core_id)
        if vswitch_pmd_cpu_mask == 0 and vswitch_vhost_cpu_map != 0:
            core_id_1 = self.cpumask2coreids(default_vswitch_pmd_cpu_mask)
            return self.cpu_allocation_check(vswitch_vhost_cpu_map, core_id_1)
        core_id_2 = self.cpumask2coreids(vswitch_pmd_cpu_mask)
        return self.cpu_allocation_check(vswitch_vhost_cpu_map, core_id_2)

    def GetVSPERFConffromDUT(self, request, context):
        """
        This will extract the vsperf test configuration from DUT-Host
        """
        if self.dut_check != 0:
            return vsperf_pb2.StatusReply(message="DUT-Host is not Connected [!]" \
                                                   "\nMake sure to establish connection with" \
                                                   " DUT-Host.")
        if self.test_upload_check == 0:
            return vsperf_pb2.StatusReply(message="Test File is not uploaded yet [!] " \
                         "\nUpload Test Configuration File.")
        read_cmd = "cat ~/{}".format(self.conffile)
        read_cmd_output = str(self.client.execute(read_cmd)[1])
        return vsperf_pb2.StatusReply(message="{}".format(read_cmd_output))


def serve():
    """
    Start servicing the client
    """
    server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
    vsperf_pb2_grpc.add_ControllerServicer_to_server(
        VsperfController(), server)
    server.add_insecure_port('[::]:50052')
    server.start()
    try:
        while True:
            time.sleep(_ONE_DAY_IN_SECONDS)
    except (SystemExit, KeyboardInterrupt, MemoryError, RuntimeError):
        server.stop(0)


if __name__ == "__main__":
    serve()