cinder/cinder/volume/drivers/huawei/huawei_utils.py

162 lines
4.7 KiB
Python

# Copyright (c) 2016 Huawei Technologies Co., Ltd.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import json
import six
import time
from oslo_log import log as logging
from oslo_service import loopingcall
from oslo_utils import units
from cinder import exception
from cinder.i18n import _
from cinder import objects
from cinder.volume.drivers.huawei import constants
from cinder.volume import utils
LOG = logging.getLogger(__name__)
def encode_name(name):
pre_name = name.split("-")[0]
vol_encoded = six.text_type(hash(name))
if vol_encoded.startswith('-'):
newuuid = pre_name + vol_encoded
else:
newuuid = pre_name + '-' + vol_encoded
return newuuid
def encode_host_name(name):
if name and (len(name) > constants.MAX_HOSTNAME_LENGTH):
name = six.text_type(hash(name))
return name
def wait_for_condition(func, interval, timeout):
start_time = time.time()
def _inner():
try:
res = func()
except Exception as ex:
raise exception.VolumeBackendAPIException(data=ex)
if res:
raise loopingcall.LoopingCallDone()
if int(time.time()) - start_time > timeout:
msg = (_('wait_for_condition: %s timed out.')
% func.__name__)
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
timer = loopingcall.FixedIntervalLoopingCall(_inner)
timer.start(interval=interval).wait()
def get_volume_size(volume):
"""Calculate the volume size.
We should divide the given volume size by 512 for the 18000 system
calculates volume size with sectors, which is 512 bytes.
"""
volume_size = units.Gi / 512 # 1G
if int(volume.size) != 0:
volume_size = int(volume.size) * units.Gi / 512
return volume_size
def get_volume_metadata(volume):
if type(volume) is objects.Volume:
return volume.metadata
if 'volume_metadata' in volume:
metadata = volume.get('volume_metadata')
return {item['key']: item['value'] for item in metadata}
return {}
def get_admin_metadata(volume):
admin_metadata = {}
if 'admin_metadata' in volume:
admin_metadata = volume.admin_metadata
elif 'volume_admin_metadata' in volume:
metadata = volume.get('volume_admin_metadata', [])
admin_metadata = {item['key']: item['value'] for item in metadata}
LOG.debug("Volume ID: %(id)s, admin_metadata: %(admin_metadata)s.",
{"id": volume.id, "admin_metadata": admin_metadata})
return admin_metadata
def get_snapshot_metadata_value(snapshot):
if type(snapshot) is objects.Snapshot:
return snapshot.metadata
if 'snapshot_metadata' in snapshot:
metadata = snapshot.snapshot_metadata
return {item['key']: item['value'] for item in metadata}
return {}
def check_whether_operate_consistency_group(func):
def wrapper(self, context, group, *args, **kwargs):
if not utils.is_group_a_cg_snapshot_type(group):
msg = _("%s, the group or group snapshot is not cg or "
"cg_snapshot") % func.__name__
LOG.debug(msg)
raise NotImplementedError(msg)
return func(self, context, group, *args, **kwargs)
return wrapper
def to_string(**kwargs):
return json.dumps(kwargs) if kwargs else ''
def get_lun_metadata(volume):
if not volume.provider_location:
return {}
info = json.loads(volume.provider_location)
if isinstance(info, dict):
return info
# To keep compatible with old driver version
admin_metadata = get_admin_metadata(volume)
metadata = get_volume_metadata(volume)
return {'huawei_lun_id': six.text_type(info),
'huawei_lun_wwn': admin_metadata.get('huawei_lun_wwn'),
'hypermetro_id': metadata.get('hypermetro_id'),
'remote_lun_id': metadata.get('remote_lun_id')
}
def get_snapshot_metadata(snapshot):
if not snapshot.provider_location:
return {}
info = json.loads(snapshot.provider_location)
if isinstance(info, dict):
return info
# To keep compatible with old driver version
return {'huawei_snapshot_id': six.text_type(info)}