# -*- 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 HCCIException
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.business.OpenStack.openstack_password_utils import DefaultPasswordManager
from utils.Driver.CloudDC.OpenStack.get_host_info import GetHostInfo
from utils.business.project_condition_utils import get_project_condition_boolean
from plugins.DistributedStorage.logic.vm_operate import VMOperate
from plugins.DistributedStorage.logic.install_operate import InstallOperate
from plugins.DistributedStorage.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 HCCIException 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, HCCIException(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 HCCIException(626102, self.float_ip)
        logger.info("Check if the fsadmin account is accessible")
        vm_data_list = self.vm_operate.get_vm_data(self.pod_id, self.float_ip)
        instanceid_list = []
        for info in vm_data_list:
            auth_info = info.get('om_ip'), info.get('user'), info.get('passwd')
            self.operate.check_user_accessible(*auth_info)
            self.operate.del_mark_file(*auth_info, info.get("root_pwd"))
            instanceid_list.append(info.get("id"))

        logger.info("restart vm")
        self.vm_operate.restart_dsware_vm(instanceid_list)
        for info in vm_data_list:
            self.operate.check_user_accessible(info.get('om_ip'), info.get('user'), info.get('passwd'))
        logger.info("The VM is successfully created.")

    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 HCCIException(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 HCCIException(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'] = DefaultPasswordManager().get_root_default_password()
        node['user'] = 'fsp'
        node['passwd'] = DefaultPasswordManager().get_fsp_default_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 HCCIException 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)
