# -*- coding: utf-8 -*-
# Copyright (c) Huawei Technologies Co., Ltd. 2022-2023. All rights reserved.
import time
import os
import traceback

import utils.common.log as logger
from utils.common.fic_base import TestCase
from utils.common.message import Message
from utils.common.exception import FCDException
from utils.common.PublicServiceOperate import ParameterQuery
from utils.constant.FCDConstant import REGION_CONTROL_HA_AZ, REGION_CONTROL_HA_SITE
from utils.client.FSPAuthClient import FSPAuthClient
from utils.business.OpenStack.cps_pkg_uploader import CpsPkgUploader
from utils.PasswordManager.PasswordManager import FSPasswordManager
from utils.Driver.CloudDC.OpenStack.get_host_info import GetHostInfo
from platforms.project.ProjectUtils import get_project_condition_boolean
from plugins.DistributedStorage.scripts.logic.vm_operate import VMOperate
from plugins.DistributedStorage.scripts.logic.InstallOperate import InstallOperate
from plugins.DistributedStorage.scripts.utils.common.general_query import GeneralQuery


class CreateVM(TestCase):
    def __init__(self, project_id, pod_id, fs_args, **kwargs):
        super(CreateVM, self).__init__(project_id, pod_id)
        self.fs_args = fs_args
        self.more_args = kwargs
        self.operate = InstallOperate(self.project_id, self.pod_id, self.fs_args)
        self.vm_operate = VMOperate(self.project_id, self.pod_id, self.fs_args)
        self.vm_status = False
        self.pkg_file_path = self.fs_args.get("uvp_install_path")

        # TC_Create_VM 新增参数
        self.create_vm_task_id = self.fs_args.get("create_vm_task_id")
        self.create_vm_subtask_id = self.fs_args.get("create_vm_subtask_id")
        self.create_vm_service_name = self.fs_args.get("create_vm_service_name")
        self.create_vm_fsm_scale = self.fs_args.get("create_vm_fsm_scale")
        self.float_ip = self.fs_args.get("float_ip")
        self.site_error_code = 626296

    def procedure(self):
        logger.info("Prepare to create VM.")
        try:
            self.create_vm_main()
        except FCDException as e:
            self.vm_status = False
            logger.error(traceback.format_exc())
            return Message(500, e)
        except Exception as e:
            self.vm_status = False
            logger.error(traceback.format_exc())
            return Message(500, FCDException(626004, str(e)))
        finally:
            self.vm_operate.update_fusionstorage_table(self.create_vm_task_id, self.create_vm_subtask_id,
                                                       self.vm_status)
        logger.info("Create VM successful")
        return Message(200)

    def create_vm_main(self):
        self.vm_operate.process_before_create_vm(self.create_vm_task_id, self.create_vm_subtask_id, self.float_ip)
        # 如果参数中没有传递待安装节点的信息则调用函数get_fsm_vm_physics_nodes获取
        if self.fs_args.get("master", None) is None and self.fs_args.get("standby", None) is None:
            self.get_fsm_vm_physics_nodes()
        logger.info("Start to create VM.")
        webui_host_and_tool = FSPAuthClient.get_cps_web_host_and_tool(self.db, self.project_id, self.pod_id)
        logger.info("Upload UVP package to cps-web.")
        cps_rest = FSPAuthClient.get_cps_rest_client(self.db, self.project_id, self.pod_id)
        pkg_path = os.path.dirname(self.pkg_file_path)
        pkg_file = os.path.basename(self.pkg_file_path)
        upload_obj = CpsPkgUploader(cps_rest)
        upload_obj.pkg_upload(pkg_file, pkg_path, timeout=2400)
        logger.info("Succeed to upload UVP package[%s/%s] to cps-web." % (pkg_path, pkg_file))
        self.vm_operate.check_float_ip_used(self.float_ip)
        fsm_query = ParameterQuery(self.create_vm_service_name, self.args_dict)
        flavor = fsm_query.get_value_from_cloudparam(self.create_vm_fsm_scale)
        vm_type = "FusionCompute"
        logger.info("Create VM")
        self.vm_operate.install_create_fsm_from_webui(host_and_tool=webui_host_and_tool, flavor=flavor,
                                                      virtualization_type=vm_type)
        query_result = self.vm_operate.query_create_fsm_from_webui(webui_host_and_tool, self.float_ip)
        if query_result:
            self.vm_status = True
            logger.info("components restart. please wait two minutes...")
            time.sleep(120)
        else:
            logger.error("Failed to create FSM VMs.")
            raise FCDException(626102, self.float_ip)
        logger.info("Check if the fsadmin account is accessible")
        vm_master, vm_standby = self.vm_operate.get_vm_data(self.pod_id, self.float_ip)
        self.operate.check_user_accessible(vm_master.get('om_ip'), vm_master.get('user'), vm_master.get('passwd'))
        self.operate.check_user_accessible(vm_standby.get('om_ip'), vm_standby.get('user'),
                                           vm_standby.get('passwd'))

    def get_fsm_vm_physics_nodes(self):
        webui_client = FSPAuthClient.get_cps_web_client(self.db, self.project_id, self.pod_id)
        cps_hosts = GetHostInfo(webui_client)
        is_manage_az_ha_in_exp_az_new_fs_scenario = get_project_condition_boolean(
            self.project_id, 'RegionConHA&TenantStorFB80&(ExpansionAZ_KVM|ExpansionAZ_BMS)')
        is_manage_az_ha_in_ipsan_exp_fs_scenario = get_project_condition_boolean(
            self.project_id, '(CSHAStorage_TFB|RegionConHA)&TenantStorFB80&ExpansionServiceStorage')
        if is_manage_az_ha_in_exp_az_new_fs_scenario:
            availability_zone = self.get_availability_zone_in_exp_az_new_fs_scenario()
            available_fsm_bmc_ip_list = GeneralQuery.select_host_of_fsm(self.db, self.project_id, self.pod_id,
                                                                        availability_zone)
        elif is_manage_az_ha_in_ipsan_exp_fs_scenario:
            availability_zone = self.get_availability_zone_in_ipsan_exp_fs_scenario()
            available_fsm_bmc_ip_list = GeneralQuery.select_host_of_fsm(self.db, self.project_id, self.pod_id,
                                                                        availability_zone)
        else:
            available_fsm_bmc_ip_list = GeneralQuery.select_host_of_fsm(self.db, self.project_id, self.pod_id)
        self.fs_args['master'] = self.get_node_data(available_fsm_bmc_ip_list[0], cps_hosts)
        self.fs_args['standby'] = self.get_node_data(available_fsm_bmc_ip_list[1], cps_hosts)

    def get_availability_zone_in_ipsan_exp_fs_scenario(self):
        manage_az_site = self.db.get_user_input_cloud_param_by_key(self.project_id, "manage_az_site")
        logger.info("manage_az_site:{}".format(manage_az_site))
        availability_zone = self.get_az_by_site(manage_az_site)
        return availability_zone

    def get_availability_zone_in_exp_az_new_fs_scenario(self):
        vbs_bmc_ip_and_site_info = {node.get("bmc_ip"): node.get("site") for node in self.fs_args.get("vbs_list")}
        logger.info("vbs bmc_ip and site info:{}".format(vbs_bmc_ip_and_site_info))
        sites_set = set(vbs_bmc_ip_and_site_info.values())
        if len(sites_set) != 1:
            logger.error("Site Error:{}".format(sites_set))
            raise FCDException(self.site_error_code, vbs_bmc_ip_and_site_info)
        site = sites_set.pop()
        availability_zone = self.get_az_by_site(site)
        return availability_zone

    def get_az_by_site(self, site):
        if site == REGION_CONTROL_HA_SITE.DC001:
            availability_zone = REGION_CONTROL_HA_AZ.MANAGE_AZ
        elif site == REGION_CONTROL_HA_SITE.DC002:
            availability_zone = REGION_CONTROL_HA_AZ.DR_MANAGE_AZ
        else:
            err_msg = "Site Error:{}".format(site)
            logger.error(err_msg)
            raise FCDException(self.site_error_code, err_msg)
        return availability_zone

    def get_node_data(self, bmc_ip, all_hosts):
        node = dict()
        bmc_list = [bmc_ip]
        master_id_list, master_ip_list = all_hosts.get_host_info(bmc_list)
        node['bmc_ip'] = bmc_ip
        node['hostname'], node['om_ip'] = master_id_list[0], master_ip_list[0]
        node['root_pwd'] = FSPasswordManager(self.pod_id).get_root_password()
        node['user'] = 'fsp'
        node['passwd'] = FSPasswordManager(self.pod_id).get_fsp_password()
        return node

    def delete_created_vm_from_cps(self):
        logger.info("Try to delete the created virtual machine")
        try:
            self.vm_operate.delete_created_vm(self.create_vm_task_id, self.create_vm_subtask_id, self.float_ip)
        except FCDException as e:
            err_msg = "Failed to delete the created virtual machine. Detail:%s" % str(e)
            logger.error(err_msg)
            logger.error(traceback.format_exc())
            return Exception(err_msg)
        except Exception as e:
            err_msg = "Failed to delete the created virtual machine. Detail:%s" % str(e)
            logger.error(err_msg)
            logger.error(traceback.format_exc())
            return Exception(err_msg)
        return Message(200)
