# -*- coding: utf-8 -*-
import traceback
import json
import utils.common.log as logger
from utils.constant.path_constant import ProjectPluginsPath
from utils.common.exception import HCCIException
from utils.DBAdapter.DBConnector import BaseOps
from plugins.DistributedStorage.logic import DeployOperate
from plugins.DistributedStorage.Deploy.scripts.PreCheck.common.DeviceOperate import CpuOperate
from plugins.DistributedStorage.utils.common.DeployConstant import DeployConstant
from utils.business.project_util import ProjectApi
from utils.business.project_condition_utils import get_project_conditions


class StorageNodeOsPackageCheck(object):
    """
    更新inspect.json文件，保证上传的存储os包与实际的cpu架构一致：
    1. 查找存储节点bmc_ip的CPU架构
    2. 删除原inspect.json文件里的os包信息
    3. 将与节点实际的cup架构匹配的os包信息（json_data）更新到inspect.json文件中
    4. 在数据库中更新inspect.json。
    """
    def __init__(self, project_id, pod_id, **kwargs):
        self.project_id = project_id
        self.pod_id = pod_id
        self.db = BaseOps()
        self.Operate = DeployOperate
        self.deploy_constant = DeployConstant()

    def procedure(self):
        try:
            logger.info('Start to update the file: inspect.json')
            plugin_path = ProjectPluginsPath.project_plugins_path()
            if get_project_conditions(self.project_id).get('ProjectDeploy'):
                scenario_path = 'Deploy'
            elif get_project_conditions(self.project_id).get('ExpansionAdCloudService'):
                scenario_path = 'Replication'
            else:
                scenario_path = 'Expansion'
            json_path = r"{}/DistributedStorage/{}/params/inspect.json".format(plugin_path, scenario_path)
            logger.info("Get plugin path:%s" % json_path)

            # 遍历节点，获取节点cpu架构
            logger.info('Query the CPU architecture of stroage node')
            arch_all = ('X86', 'ARM')
            arch_set = set()
            node_info = self.db.get_install_os_list_info(self.pod_id) + \
                        self.db.get_install_os_list_info(self.pod_id, 'rep')
            bmc_ip_list = [node['bmc_ip'] for node in node_info]
            operate = CpuOperate()
            cpu_arch_dict = operate.get_system_arch(bmc_ip_list)
            for node in node_info:
                bmc_ip = node.get('bmc_ip')
                arch = cpu_arch_dict.get(bmc_ip).get('stdout')
                if arch not in arch_all:
                    err_msg = 'Failed: The actual CPU architecture of ' \
                              'the node {}：{}'.format(bmc_ip, arch)
                    logger.error(err_msg)
                    raise Exception(err_msg)
                arch_set.add(arch)

            # 获取工程条件
            _condition = get_project_conditions(self.project_id)
            logger.info(f'project  conditions is {_condition}')
            project_condition = []
            for k, v in _condition.items():
                if v:
                    project_condition.append(k)
            project_condition = '&'.join(project_condition)

            # 创建需要校验的os包信息列表
            logger.info('Creating a list of package information '
                        'corresponding to the CPU architecture')
            need_pkgs = list()
            for arch_tmp in arch_set:
                if arch_tmp == 'X86':
                    need_pkgs.append(
                        self.deploy_constant.STORAGE_PACKAGES_PATTERN[2]
                    )
                if arch_tmp == 'ARM':
                    need_pkgs.append(
                        self.deploy_constant.STORAGE_PACKAGES_PATTERN[3]
                    )

            # 编辑json文件，删除原os包信息，写入新os包信息
            logger.info('Modify the file: inspect.json')
            pkg_index = set()
            pkg_delete = list()
            with open(json_path, 'r', encoding='utf-8') as file_inspect_json:
                json_dict = json.load(file_inspect_json)
            pkg_define_list = json_dict.get('pkg_define')
            for i, pkg_info in enumerate(pkg_define_list):
                pkg_name_tmp = pkg_info.get('pkgs')
                for each_pkg in pkg_name_tmp:
                    if each_pkg.get('OceanStor-Pacific_8.1.*_OS-*x86*64*.tgz', '') or \
                            each_pkg.get('OceanStor-Pacific_8.1.*_OS-*aarch64*.tgz', ''):
                        pkg_index.add(i)
            for j in pkg_index:
                pkg_delete.append(pkg_define_list[j])
            for tmp in pkg_delete:
                json_dict.get('pkg_define').remove(tmp)
            logger.info("Update the package information to the 'inspect.json'")
            json_data = {"project_condition": project_condition, "pkgs": need_pkgs}
            json_dict['pkg_define'].append(json_data)
            with open(json_path, 'w', encoding='utf-8') as file_inspect_json:
                file_inspect_json.write(
                    json.dumps(json_dict, indent=2, ensure_ascii=False)
                )
            # 将inspect.json文件更新入数据库
            logger.info('Add package information to db')
            ProjectApi.update_project_pkg_verify_status(self.project_id, False)
            logger.info('Update completed!!!')
        except HCCIException as e:
            logger.error('Failed: {}'.format(traceback.format_exc()))
            raise Exception(str(e))
        except Exception as e:
            logger.error('Failed: {}'.format(traceback.format_exc()))
            raise Exception(str(e))
