__author__ = 'Administrator'
import json
import time
import random

from cinder.volume import driver
from hwcloud.database_manager import DatabaseManager
from hwcloud.hws_service.client import HWSClient
from cinder.openstack.common import log as logging
from cinder.volume.drivers.hws import sshutils as sshclient

from oslo.config import cfg

from keystoneclient.v2_0 import client as kc
from cinder.openstack.common import fileutils
from cinder.openstack.common import excutils
from cinder.image import image_utils
import traceback
import string
import os

hws_opts = [cfg.StrOpt('project_id', help='project_id'),
            cfg.StrOpt('flavor_id', help='flavor id'),
            cfg.StrOpt('vpc_id', help='vpc_id'),
            cfg.StrOpt('subnet_id', help='subnet_id'),
            cfg.StrOpt('image_id', help='image_id'),
            cfg.StrOpt('gong_yao', help='gong yao'),
            cfg.StrOpt('si_yao', help='si yao'),
            cfg.StrOpt('service_region', help='region where resource to create in'),
            cfg.StrOpt('resource_region', help='region where resource to create in'),
            cfg.StrOpt('service_protocol', help='protocol', default='https'),
            cfg.StrOpt('service_port', help='port', default='443'),
            cfg.StrOpt('volume_type', help='default volume_typ', default='SATA')]

CONF = cfg.CONF
hws_group = 'hws'
CONF.register_opts(hws_opts, hws_group)

remote_vgw_keystone_opts = [
    cfg.StrOpt('tenant_name',
               default='admin',
               help='tenant name for connecting to keystone in admin context'),
    cfg.StrOpt('user_name',
               default='cloud_admin',
               help='username for connecting to cinder in admin context'),
    cfg.StrOpt('keystone_auth_url',
               default='https://identity.cascading.hybrid.huawei.com:443/identity-admin/v2.0',
               help='value of keystone url'),
]
remote_vgw_keystone_group = 'keystone_authtoken'
CONF.register_opts(remote_vgw_keystone_opts, remote_vgw_keystone_group)


hws_vgw_opts = [
    cfg.StrOpt('user_name',
               default='root',
               help='user name for local az hws v2v gateway host'),
    cfg.StrOpt('password',
               default='Huawei@CLOUD8!',
               help='password for local az hws v2v gateway host'),
    cfg.StrOpt('host_ip',
               default='172.21.0.23',
               help='ip for local az hws v2v gateway host'),
    cfg.StrOpt('ssh_retry_times',
               default='3',
               help='ssh retry times'),
    cfg.StrOpt('hws_instance_id',
               # default='72dca101-e822-4923-a3a1-ffac838ff5d5',
               default='a83325ee-4917-4896-9eac-227f5934115a',
               help='hws vgw instance id'),
    cfg.StrOpt('hws_vgw_ip',
               # default='117.78.35.163',
               default='117.78.36.181',
               help='hws vgw instance id'),
]

hws_vgw_group = 'hws_vgw'
CONF.register_opts(hws_vgw_opts, hws_vgw_group)


LOG = logging.getLogger(__name__)

SATA = 'SATA'
SSD = 'SSD'
SAS = 'SAS'
SUPPORT_VOLUME_TYPE = [SATA, SSD, SAS]

HWS_SERVER_STATUS = {
    'active': 'ACTIVE',
    'shutoff': 'SHUTOFF'
}

HWS_REAL_DEVNAME = {
    '/dev/sda': '/dev/xvda',
    '/dev/sdb': '/dev/xvde',
    '/dev/sdc': '/dev/xvdf',
    '/dev/sdd': '/dev/xvdg',
    '/dev/sde': '/dev/xvdh',
    '/dev/sdf': '/dev/xvdi',
    '/dev/sdg': '/dev/xvdj',
    '/dev/sdh': '/dev/xvdk',
    '/dev/sdi': '/dev/xvdl',
    '/dev/sdj': '/dev/xvdm',
    '/dev/sdk': '/dev/xvdn'
}

class HWSDriver(driver.VolumeDriver):
    VERSION = "1.0"

    def __init__(self, *args, **kwargs):
        super(HWSDriver, self).__init__( *args, **kwargs)
        gong_yao = CONF.hws.gong_yao
        si_yao = CONF.hws.si_yao
        region = CONF.hws.service_region
        protocol = CONF.hws.service_protocol
        port = CONF.hws.service_port
        self.hws_client = HWSClient(gong_yao, si_yao, region, protocol, port)
        self.db_manager = DatabaseManager()
        self.project_id = CONF.hws.project_id
        self.availability_zone = CONF.hws.resource_region
        self.volume_type_default = CONF.hws.volume_type

        self.hws_vgw_user = CONF.hws_vgw.user_name
        self.hws_vgw_password = CONF.hws_vgw.password
        self.hws_wgw_ip = CONF.hws_vgw.host_ip
        self.hws_vgw_ip = CONF.hws_vgw.hws_vgw_ip

    def create_volume(self, volume):
        """Create a volume.
        """
        LOG.info('VOLUME: %s' % dir(volume))
        LOG.info('IMAGE ID: %s' % volume.get('image_id'))
        if not volume.get('image_id'):
            volume_name = self._get_display_name(volume)
            project_id = self.project_id
            size = volume.size
            volume_type = self.volume_type_default

            job_info = self.hws_client.evs.create_volume(project_id, self.availability_zone,
                                                         size, volume_type, name=volume_name)
            self._deal_with_job(job_info, project_id, self._add_volume_mapping_to_db, None, volume)
        else:
            return {'provider_location': 'HWS CLOUD'}

    def _get_display_name(self, volume):
        original_display_name = volume.display_name
        if len(original_display_name) < 20:
            display_name = original_display_name
        else:
            display_name = self._get_random_name(8)

        return display_name

    def _get_random_name(self, length):
        return ''.join(random.sample(string.ascii_letters + string.digits, length))

    def _get_instance_volume_list(self, instance_id):
        """

        :param project_id: string, hws project id
        :param volume_id: string, hws volume id
        :return volume_list_rsp:
        """
        volume_list_rsp = self.hws_client.ecs.get_volume_list(self.project_id, instance_id)
        if volume_list_rsp['status'] != 200:
            error_info = 'hws_v2v: get hws v2v gateway host volume list error, Exception: %s' \
                         % json.dumps(volume_list_rsp)
            LOG.error(error_info)
            raise Exception(error_info)
        return volume_list_rsp

    def _get_volume_detail(self, volume_id):
        """

        :param project_id: string, hws project id
        :param volume_id: string, hws volume id
        :return volume_detail_rsp:
        """
        volume_detail_rsp = self.hws_client.evs.get_volume_detail(self.project_id, volume_id)
        if volume_detail_rsp['status'] != 200: