# -*- coding: utf-8 -*-
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@文件  :result_post_linux.py
@说明  :回调接口,linux版
@时间  :2020/10/23 16:36:02
@作者  :dutianxing
@版本  :1.0
'''

import json,urllib,time, hashlib, sys,requests,os,base64,random,string
import logging
import logging.config
import subprocess

logger = logging.getLogger("simple_example")
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s %(levelname)-8s %(message)s', '%a, %d %b %Y %H:%M:%S',)
file_handler = logging.FileHandler("/var/log/result_post.log")
file_handler.setLevel(logging.DEBUG)
file_handler.setFormatter(formatter)
stream_handler = logging.StreamHandler(sys.stderr)
logger.addHandler(file_handler)
logger.addHandler(stream_handler)

class PostOperation():
    def execute(self):
        logger.info("--------------------------Result Post start-----------------------------------------")
        meta_info=self.get_record_meta()
        url = meta_info['patch_host']+'/api/cdserv/cloudupdate/sendFinishInfo'
        uuid = meta_info['uuid']
        name = meta_info['name']
        if self.is_base64_code(name):
            name_byte=base64.b64decode(name)
            name=bytes.decode(name_byte)
        ACCESS_KEY = "cloud_desktop_2@19@@#$!!PPKJ"
        checksum = self.sha256_single(uuid+name+ACCESS_KEY)
        logger.info("checkSum is "+checksum)
        #运行自定义命令
        shell_base_url=self.get_record_extend("script_minio_url")
        if shell_base_url:
            logger.info("script minio url is "+str(shell_base_url))
            response=requests.get(url=shell_base_url)
            if response.content:
                decoded_test = base64.b64decode(response.content).decode('utf-8')
                logger.info(decoded_test)
                subprocess.run(decoded_test, shell=True)
        #回调
        self.post_status(url,uuid,name,checksum)
        logger.info('The Computer initialization complete.')

    unpad = lambda s: s[:-ord(s[len(s) - 1:])]

    def is_base64_code(self,s):
        '''Check s is Base64.b64encode'''
        if not isinstance(s ,str) or not s:
            raise ValueError

        _base64_code = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
                        'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R',
                        'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a',
                        'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
                        'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's',
                        't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1',
                        '2', '3', '4','5', '6', '7', '8', '9', '+',
                        '/', '=' ]

        # Check base64 OR codeCheck % 4
        code_fail = [ i for i in s if i not in _base64_code]
        if code_fail or len(s) % 4 != 0:
            return False
        return True

    def sha256_single(self,value):
        """
        sha256加密
        :param value: 加密字符串
        :return: 加密结果转换为16进制字符串，并小写
        """
        hsobj = hashlib.sha256()
        hsobj.update(value.encode("utf-8"))
        return hsobj.hexdigest().lower()

    def post_status(self,url,uuid,name,checksum):
        requestData = {
            "osUuid":uuid, 
            "desktopName":name,
            "checkSum":checksum
        }
        logger.info(requestData)
        try:
            headers = {'Content-Type': 'application/json'}
            # verify=False 为绕过https的ssl加密
            response = requests.post(url=url,headers=headers,verify=False,data = json.dumps(requestData))
            #response = urlopen(request_message)
            logger.info("the response message is :")
            if response.content:
                logger.info(response.json())
            n=5
        except Exception as e:
            logger.exception('post operation is failed')
            n=n+1
            time.sleep(30)


    def get_record_meta(self,info=None):
        n=3
        while n>0:
            release_cmd="dmidecode --oem-string 1"
            p=os.popen(release_cmd)
            #logging.info(p.read())
            result_str=p.read()
            p.close()
            logger.info("result_str"+result_str)
            if result_str:
                try:
                    result_json = json.loads(result_str)
                    if info:
                        meta_data = result_json[info]
                        return meta_data
                    else:
                        return result_json
                except KeyError:
                    logger.error('Could not find meta info from wmic.')
                    continue
            else:
                logger.info("Could not get metadata from wmic, net may have trouble.Waiting 10s and retry.")
                time.sleep(10)
                n=n-1
                continue
        meta_data=""
        return meta_data
    
    def get_record_extend(self,info,is_retry=True):
        n=3
        while n>0:
            try:
                meta_info=self.get_record_meta()
                url = meta_info['patch_host']+'/api/openApi/cdserv/api/metadata/realTime/getMap'
                logger.info(url)
                uuid = meta_info['uuid']
                api_key = '9f8b602b9d90314a24af41c11b459561'
                api_secret = '033d69ff3a6d6a2b2d14e5f7237e4166'
                nonStr = ''.join(random.sample(string.digits + string.ascii_letters,8))
                #logging.info(nonStr)
                current_time = int(time.time())
                url_pre = 'apiKey=' + api_key + '&codes=' + info + '&nonStr=' + nonStr + '&osUUID=' + uuid + '&timestamp=' + str(current_time)
                input_string = url_pre + api_secret
                sign = hashlib.md5(input_string.encode("utf8")).hexdigest()
                url = url +'?'+ url_pre + '&sign=' + sign
                logger.info("url is "+str(url))
                params={"osUUID":uuid,"code":info,"apiKey":api_key,"nonStr":nonStr,"timestamp":str(current_time),"sign":sign}
                response=requests.get(url=url)#,params=params)
                if response.content:
                    res_json=response.json()
                    logger.info(res_json)
                    
                if res_json['code'] == 500 or not res_json['data']:
                    logger.info("Could not get meta info from http /api/metadata/get")
                    n=n-1
                else:
                    return res_json['data'][info]
            except  KeyError as e:
                logger.info("Could not get meta info '"+info+"' from http /api/metadata/get")
                n=n-1
            except Exception as e:
                logger.info(e)
                logger.info('getapi operation is failed')
                n=n-1
        return

if __name__ == '__main__':
    try:
        PostOperation().execute()
    except Exception as e:
        logger.exception(e)

