# -*- coding: utf-8 -*-
import time
import os
import traceback

from utils.common.fic_base import TestCase
import utils.common.log as logger
from utils.common.message import Message
from utils.constant.FCDConstant import REGION_CONTROL_HA_AZ, REGION_CONTROL_HA_SITE
from utils.business.project_condition_utils import get_project_condition_boolean
from utils.client.FSPAuthClient import FSPAuthClient
from utils.common.PublicServiceOperate import ParameterQuery
from plugins.DistributedStorage.logic.InstallOperate import InstallOperate
from plugins.DistributedStorage.logic.VMOperate import VMOperate
from utils.business.OpenStack.cps_pkg_uploader import CpsPkgUploader
from utils.common.exception import HCCIException
from utils.Driver.CloudDC.OpenStack.get_host_info import GetHostInfo
from utils.PasswordManager.PasswordManager import FSPasswordManager
from plugins.DistributedStorage.utils.common.generalQuery import GeneralQuery


class CreateVM(TestCase):
    def __init__(self, project_id, pod_id, fs_args, condition=None, metadata=None, **kwargs):
        super(CreateVM, self).__init__(project_id, pod_id)
        self.fs_args = fs_args
        self.condition = condition
        self.metadata = metadata
        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):
        try:
            logger.info("Prepare to create VM.")
            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,
                                                          VirtualizationType=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_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'))
            logger.info("Create VM successful")
        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)
        return Message(200)

    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'] = 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 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)
