<commit_before>import base64
import hashlib
import hmac
import pprint
import requests
import time
import urllib

import jsonHelper
from marvin.cloudstackAPI import queryAsyncJobResult
from marvin.cloudstackException import InvalidParameterException
from marvin.codes import (
    FAILED,
    JOB_FAILED,
    JOB_CANCELLED,
    JOB_SUCCEEDED
)


class CSConnection(object):
    '''
    @Desc: Connection Class to make API\Command calls to the
           CloudStack Management Server
           Sends the GET\POST requests to CS based upon the
           information provided and retrieves the parsed response.
    '''

    def __init__(self, mgmtDet, asyncTimeout=3600, logger=None,
                 path='client/api'):
        self.apiKey = mgmtDet.apiKey
        self.securityKey = mgmtDet.securityKey
        self.mgtSvr = mgmtDet.mgtSvrIp
        self.port = mgmtDet.port
        self.user = mgmtDet.user
        self.passwd = <PASSWORD>
        self.certPath = ()
        if mgmtDet.certCAPath != "NA" and mgmtDet.certPath != "NA":
            self.certPath = (mgmtDet.certCAPath, mgmtDet.certPath)
        self.logger = logger
        self.pretty_printer = pprint.PrettyPrinter(width=1)
        self.path = path
        self.retries = 5
        self.__lastError = ''
        self.mgtDetails = mgmtDet
        self.asyncTimeout = asyncTimeout
        self.auth = True
        if self.port == 8096 or \
                (self.apiKey is None and self.securityKey is None):
            self.auth = False
        self.protocol = "https" if mgmtDet.useHttps == "True" else "http"
        self.httpsFlag = True if self.protocol == "https" else False
        self.baseUrl = "%s://%s:%d/%s" \
                       % (self.protocol, self.mgtSvr, self.port, self.path)

    def __copy__(self):
        return CSConnection(self.mgtDetails,
                            self.asyncTimeout,
                            self.logger,
                            self.path)

    def __poll(self, jobid, response_cmd):
        '''
        @Name : __poll
        @Desc: polls for the completion of a given jobid
        @Input 1. jobid: Monitor the Jobid for CS
               2. response_cmd:response command for request cmd
        @return: FAILED if jobid is cancelled,failed
                 Else return async_response
        '''
        try:
            cmd = queryAsyncJobResult.queryAsyncJobResultCmd()
            cmd.jobid = jobid
            timeout = self.asyncTimeout
            start_time = time.time()
            end_time = time.time()
            async_response = FAILED
            self.logger.debug("=== Jobid: %s Started ===" % (str(jobid)))
            while timeout > 0:
                async_response = self.marvinRequest(cmd, response_type=response_cmd)
                if async_response != FAILED:
                    job_status = async_response.jobstatus
                    if job_status in [JOB_CANCELLED, JOB_SUCCEEDED]:
                        break
                    elif job_status == JOB_FAILED:
                        raise Exception("Job failed: %s" % async_response)
                time.sleep(5)
                timeout -= 5
                self.logger.debug("=== JobId: %s is Still Processing, Will TimeOut in: %s ====" %
                                  (str(jobid), str(timeout)))
            end_time = time.time()
            tot_time = int(start_time - end_time)
            self.logger.debug("=== Jobid: %s ; StartTime: %s ; EndTime: %s ; TotalTime: %s ===" %
                              (str(jobid), str(time.ctime(start_time)), str(time.ctime(end_time)), str(tot_time)))
            return async_response
        except Exception as e:
            self.__lastError = e
            self.logger.exception("==== __poll: Exception Occurred :%s ====" % str(self.__lastError))
            return FAILED

    def getLastError(self):
        '''
        @Name : getLastError
        @Desc : Returns the last error from marvinRequest
        '''
        return self.__lastError

    def __sign(self, payload):
        """
        @Name : __sign
        @Desc:signs a given request URL when the apiKey and
              secretKey are known
        @Input: payload: dictionary of params be signed
        @Output: the signature of the payload
        """
        params = zip(payload.keys(), payload.values())
        params.sort(key=lambda k: str.lower(k[0]))
        hash_str = "&".join(
            ["=".join(
                [str.lower(r[0]),
                 str.lower(
                     urllib.quote_plus(str(r[1]))
                 ).replace("+", "%20")]
            ) for r in params]
        )
        signature = base64.encodestring(hmac.new(
            self.securityKey, hash_str, hashlib.sha1).digest()).strip()
        return signature

    def __sendPostReqToCS(self, url, payload):
        '''
        @Name : __sendPostReqToCS
        @Desc : Sends the POST Request to CS
        @Input : url: URL to send post req
                 payload:Payload information as part of request
        @Output: Returns response from POST output
                 else FAILED
        '''
        try:
            response = requests.post(url, params=payload, cert=self.certPath, verify=self.httpsFlag)
            return response
        except Exception as e:
            self.__lastError = e
            self.logger.exception("__sendPostReqToCS : Exception Occurred: %s" % str(self.__lastError))
            return FAILED

    def __sendGetReqToCS(self, url, payload):
        '''
        @Name : __sendGetReqToCS
        @Desc : Sends the GET Request to CS
        @Input : url: URL to send post req
                 payload:Payload information as part of request
        @Output: Returns response from GET output
                 else FAILED
        '''
        try:
            return requests.get(url, params=payload, cert=self.certPath, verify=self.httpsFlag)
        except Exception as e:
            self.__lastError = e
            self.logger.exception("__sendGetReqToCS : Exception Occurred: %s" % str(self.__lastError))
            return FAILED

    def __sendCmdToCS(self, command, auth=True, payload={}, method='GET'):
        """
        @Name : __sendCmdToCS
        @Desc : Makes requests to CS using the Inputs provided
        @Input: command: cloudstack API command name
                    eg: deployVirtualMachineCommand
                auth: Authentication (apikey,secretKey) => True
                     else False for integration.api.port
                payload: request data composed as a dictionary
                method: GET/POST via HTTP
        @output: FAILED or else response from CS
        """
        try:
            payload["command"] = command
            payload["response"] = "json"

            if auth:
                payload["apiKey"] = self.apiKey
                payload["signature"] = self.__sign(payload)

            # Verify whether protocol is "http" or "https", then send the
            # request
            if self.protocol in ["http", "https"]:
                command_name = self.pretty_printer.pformat(command)
                self.logger.debug("======= Sending %s Cmd : %s =======" % (method, command_name))
                if 'queryAsyncJobResult' in command_name:
                    self.logger.debug("Payload: %s" % str(payload))
                if method == 'POST':
                    return self.__sendPostReqToCS(self.baseUrl, payload)
                if method == 'GET':
                    return self.__sendGetReqToCS(self.baseUrl, payload)
            else:
                self.logger.exception("__sendCmdToCS: Invalid Protocol")
                return FAILED
        except Exception as e:
            self.__lastError = e<commit_msg>Fix log check for query async job (invert logic)<commit_after>import base64
import hashlib
import hmac
import pprint
import requests
import time
import urllib

import jsonHelper
from marvin.cloudstackAPI import queryAsyncJobResult
from marvin.cloudstackException import InvalidParameterException
from marvin.codes import (
    FAILED,
    JOB_FAILED,
    JOB_CANCELLED,
    JOB_SUCCEEDED
)


class CSConnection(object):
    '''
    @Desc: Connection Class to make API\Command calls to the
           CloudStack Management Server
           Sends the GET\POST requests to CS based upon the
           information provided and retrieves the parsed response.
    '''

    def __init__(self, mgmtDet, asyncTimeout=3600, logger=None,
                 path='client/api'):
        self.apiKey = mgmtDet.apiKey
        self.securityKey = mgmtDet.securityKey
        self.mgtSvr = mgmtDet.mgtSvrIp
        self.port = mgmtDet.port
        self.user = mgmtDet.user
        self.passwd = mgmtDet.passwd
        self.certPath = ()
        if mgmtDet.certCAPath != "NA" and mgmtDet.certPath != "NA":
            self.certPath = (mgmtDet.certCAPath, mgmtDet.certPath)
        self.logger = logger
        self.pretty_printer = pprint.PrettyPrinter(width=1)
        self.path = path
        self.retries = 5
        self.__lastError = ''
        self.mgtDetails = mgmtDet
        self.asyncTimeout = asyncTimeout
        self.auth = True
        if self.port == 8096 or \
                (self.apiKey is None and self.securityKey is None):
            self.auth = False
        self.protocol = "https" if mgmtDet.useHttps == "True" else "http"
        self.httpsFlag = True if self.protocol == "https" else False
        self.baseUrl = "%s://%s:%d/%s" \
                       % (self.protocol, self.mgtSvr, self.port, self.path)

    def __copy__(self):
        return CSConnection(self.mgtDetails,
                            self.asyncTimeout,
                            self.logger,
                            self.path)

    def __poll(self, jobid, response_cmd):
        '''
        @Name : __poll
        @Desc: polls for the completion of a given jobid
        @Input 1. jobid: Monitor the Jobid for CS
               2. response_cmd:response command for request cmd
        @return: FAILED if jobid is cancelled,failed
                 Else return async_response
        '''
        try:
            cmd = queryAsyncJobResult.queryAsyncJobResultCmd()
            cmd.jobid = jobid
            timeout = self.asyncTimeout
            start_time = time.time()
            end_time = time.time()
            async_response = FAILED
            self.logger.debug("=== Jobid: %s Started ===" % (str(jobid)))
            while timeout > 0:
                async_response = self.marvinRequest(cmd, response_type=response_cmd)
                if async_response != FAILED:
                    job_status = async_response.jobstatus
                    if job_status in [JOB_CANCELLED, JOB_SUCCEEDED]:
                        break
                    elif job_status == JOB_FAILED:
                        raise Exception("Job failed: %s" % async_response)
                time.sleep(5)
                timeout -= 5
                self.logger.debug("=== JobId: %s is Still Processing, Will TimeOut in: %s ====" %
                                  (str(jobid), str(timeout)))
            end_time = time.time()
            tot_time = int(start_time - end_time)
            self.logger.debug("=== Jobid: %s ; StartTime: %s ; EndTime: %s ; TotalTime: %s ===" %
                              (str(jobid), str(time.ctime(start_time)), str(time.ctime(end_time)), str(tot_time)))
            return async_response
        except Exception as e:
            self.__lastError = e
            self.logger.exception("==== __poll: Exception Occurred :%s ====" % str(self.__lastError))
            return FAILED

    def getLastError(self):
        '''
        @Name : getLastError
        @Desc : Returns the last error from marvinRequest
        '''
        return self.__lastError

    def __sign(self, payload):
        """
        @Name : __sign
        @Desc:signs a given request URL when the apiKey and
              secretKey are known
        @Input: payload: dictionary of params be signed
        @Output: the signature of the payload
        """
        params = zip(payload.keys(), payload.values())
        params.sort(key=lambda k: str.lower(k[0]))
        hash_str = "&".join(
            ["=".join(
                [str.lower(r[0]),
                 str.lower(
                     urllib.quote_plus(str(r[1]))
                 ).replace("+", "%20")]
            ) for r in params]
        )
        signature = base64.encodestring(hmac.new(
            self.securityKey, hash_str, hashlib.sha1).digest()).strip()
        return signature

    def __sendPostReqToCS(self, url, payload):
        '''
        @Name : __sendPostReqToCS
        @Desc : Sends the POST Request to CS
        @Input : url: URL to send post req
                 payload:Payload information as part of request
        @Output: Returns response from POST output
                 else FAILED
        '''
        try:
            response = requests.post(url, params=payload, cert=self.certPath, verify=self.httpsFlag)
            return response
        except Exception as e:
            self.__lastError = e
            self.logger.exception("__sendPostReqToCS : Exception Occurred: %s" % str(self.__lastError))
            return FAILED

    def __sendGetReqToCS(self, url, payload):
        '''
        @Name : __sendGetReqToCS
        @Desc : Sends the GET Request to CS
        @Input : url: URL to send post req
                 payload:Payload information as part of request
        @Output: Returns response from GET output
                 else FAILED
        '''
        try:
            return requests.get(url, params=payload, cert=self.certPath, verify=self.httpsFlag)
        except Exception as e:
            self.__lastError = e
            self.logger.exception("__sendGetReqToCS : Exception Occurred: %s" % str(self.__lastError))
            return FAILED

    def __sendCmdToCS(self, command, auth=True, payload={}, method='GET'):
        """
        @Name : __sendCmdToCS
        @Desc : Makes requests to CS using the Inputs provided
        @Input: command: cloudstack API command name
                    eg: deployVirtualMachineCommand
                auth: Authentication (apikey,secretKey) => True
                     else False for integration.api.port
                payload: request data composed as a dictionary
                method: GET/POST via HTTP
        @output: FAILED or else response from CS
        """
        try:
            payload["command"] = command
            payload["response"] = "json"

            if auth:
                payload["apiKey"] = self.apiKey
                payload["signature"] = self.__sign(payload)

            # Verify whether protocol is "http" or "https", then send the
            # request
            if self.protocol in ["http", "https"]:
                command_name = self.pretty_printer.pformat(command)
                self.logger.debug("======= Sending %s Cmd : %s =======" % (method, command_name))
                if 'queryAsyncJobResult' not in command_name:
                    self.logger.debug("Payload: %s" % str(payload))
                if method == 'POST':
                    return self.__sendPostReqToCS(self.baseUrl, payload)
                if method == 'GET':
                    return self.__sendGetReqToCS(self.baseUrl, payload)
            else:
                self.logger.exception("__sendCmdToCS: Invalid Protocol")
                return FAILED
        except Exception as e:
            self.__lastError = e
{'fraction_non_alphanumeric': 0.09448058221163136, 'fraction_numerical': 0.0032201970760610548, 'mean_word_length': 1.7773206939724557, 'pattern_counts': {'":': 2, '<': 4, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1857312', 'n_tokens_mistral': 4233, 'n_tokens_neox': 4097, 'n_words': 1144}