Skip to content

Commit

Permalink
Merge pull request #10 from Huawei/2.1.0
Browse files Browse the repository at this point in the history
Cinder driver report "provisioned_capacity_gb". If update the driver, please restart the cinder-scheduler service.
  • Loading branch information
doubletao318 authored Apr 10, 2020
2 parents 21c1427 + 7470f79 commit 02cae27
Show file tree
Hide file tree
Showing 22 changed files with 795 additions and 35 deletions.
10 changes: 10 additions & 0 deletions Cinder/Pike/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,15 @@
QOS_SUPPORT_SCHEDULE_VERSION = "8.0"
SECONDS_OF_DAY = 24 * 60 * 60
SECONDS_OF_HOUR = 60 * 60
SNAPSHOT_HEALTH_STATUS = (
SNAPSHOT_HEALTH_STATS_NORMAL,
SNAPSHOT_HEALTH_STATS_FAULT) = (1, 2)
SNAPSHOT_RUNNING_STATUS = (
SNAPSHOT_RUNNING_STATUS_ONLINE,
SNAPSHOT_RUNNING_STATUS_OFFLINE,
SNAPSHOT_RUNNING_STATUS_ROLLBACKING) = (27, 28, 44)
SNAPSHOT_ROLLBACK_PROGRESS_FINISH = 100
SNAPSHOT_ROLLBACK_TIMEOUT = 60 * 60 * 24
WAIT_INTERVAL = 10
WEEK_DAYS = ["Sun", "Mon", "Tue", "Wed", "Thur", "Fri", "Sat"]
TIMEZONE = {"Asia/Beijing": "Asia/Shanghai"}
63 changes: 62 additions & 1 deletion Cinder/Pike/dsware.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from cinder.i18n import _
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.fusionstorage import constants
from cinder.volume.drivers.fusionstorage import fs_client
from cinder.volume.drivers.fusionstorage import fs_conf
from cinder.volume.drivers.fusionstorage import fs_flow
Expand Down Expand Up @@ -107,7 +108,13 @@
default=[],
help='The ips of FSA node were used to find the target '
'initiator and target ips in ISCSI initialize connection.'
' For example: "target_ips = ip1, ip2"')
' For example: "target_ips = ip1, ip2"'),
cfg.IntOpt('scan_device_timeout',
default=3,
help='scan_device_timeout indicates the waiting time for '
'scanning device disks on the host. It only takes effect'
' on SCSI. Default value is 3, the type is Int, the unit '
'is seconds. For example: "scan_device_timeout = 5"')
]

CONF = cfg.CONF
Expand Down Expand Up @@ -184,8 +191,10 @@ def _get_capacity(self, pool_info):
total = float(pool_info['totalCapacity']) / units.Ki
free = (float(pool_info['totalCapacity']) -
float(pool_info['usedCapacity'])) / units.Ki
provisioned = float(pool_info['usedCapacity']) / units.Ki
pool_capacity['total_capacity_gb'] = total
pool_capacity['free_capacity_gb'] = free
pool_capacity['provisioned_capacity_gb'] = provisioned

return pool_capacity

Expand All @@ -196,6 +205,7 @@ def _update_single_pool_info_status(self, pool_info):
"pool_name": pool_info['poolName'],
"total_capacity_gb": capacity['total_capacity_gb'],
"free_capacity_gb": capacity['free_capacity_gb'],
"provisioned_capacity_gb": capacity['provisioned_capacity_gb'],
"QoS_support": True,
'multiattach': True,
})
Expand Down Expand Up @@ -543,6 +553,52 @@ def retype(self, context, volume, new_type, diff, host):

return True, None

def _rollback_snapshot(self, vol_name, snap_name):
def _snapshot_rollback_finish():
snapshot_info = self.client.get_snapshot_info_by_name(snap_name)
if not snapshot_info:
msg = (_("Failed to get rollback info with snapshot %s.")
% snap_name)
self._raise_exception(msg)

if snapshot_info.get('health_status') not in (
constants.SNAPSHOT_HEALTH_STATS_NORMAL,):
msg = _("The snapshot %s is abnormal.") % snap_name
self._raise_exception(msg)

if (snapshot_info.get('rollback_progress') ==
constants.SNAPSHOT_ROLLBACK_PROGRESS_FINISH or
snapshot_info.get('rollback_endtime')):
LOG.info("Snapshot %s rollback successful.", snap_name)
return True
return False

if fs_utils.is_snapshot_rollback_available(self.client, snap_name):
self.client.rollback_snapshot(vol_name, snap_name)

try:
fs_utils.wait_for_condition(
_snapshot_rollback_finish, constants.WAIT_INTERVAL,
constants.SNAPSHOT_ROLLBACK_TIMEOUT)
except exception.VolumeBackendAPIException:
self.client.cancel_rollback_snapshot(snap_name)
raise

def revert_to_snapshot(self, context, volume, snapshot):
vol_name = self._get_vol_name(volume)
snap_name = self._get_snapshot_name(snapshot)
if not self._check_snapshot_exist(snapshot.volume, snapshot):
msg = _("Snapshot: %(name)s does not exist!"
) % {"name": snap_name}
self._raise_exception(msg)

if not self._check_volume_exist(volume):
msg = _("Volume: %(vol_name)s does not exist!"
) % {'vol_name': vol_name}
self._raise_exception(msg)

self._rollback_snapshot(vol_name, snap_name)

def create_export(self, context, volume, connector):
pass

Expand Down Expand Up @@ -604,6 +660,11 @@ def initialize_connection(self, volume, connector):
vol_wwn = volume_info.get('wwn')
by_id_path = "/dev/disk/by-id/" + "wwn-0x%s" % vol_wwn
properties = {'device_path': by_id_path}
import time
LOG.info("Wait %(t)s second(s) for scanning the target device %(dev)s."
% {"t": self.configuration.scan_device_timeout,
"dev": by_id_path})
time.sleep(self.configuration.scan_device_timeout)
return {'driver_volume_type': 'local',
'data': properties}

Expand Down
34 changes: 33 additions & 1 deletion Cinder/Pike/fs_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,13 @@ def call(self, url, method, data=None,
return self._deal_call_result(result, filter_flag, json_flag, req_dict)

def _assert_rest_result(self, result, err_str):
if result.get('result') != 0:
if isinstance(result.get('result'), dict):
if result['result'].get("code") != 0:
msg = (_('%(err)s\nresult: %(res)s.') % {'err': err_str,
'res': result})
LOG.error(msg)
raise exception.VolumeBackendAPIException(data=msg)
elif result.get('result') != 0:
msg = (_('%(err)s\nresult: %(res)s.') % {'err': err_str,
'res': result})
LOG.error(msg)
Expand Down Expand Up @@ -577,3 +583,29 @@ def get_time_config(self):
if result.get("data"):
return result.get("data")[0]
return {}

def get_snapshot_info_by_name(self, snapshot_name):
url = "/api/v2/block_service/snapshots"
params = {"name": snapshot_name}
result = self.call(url, "GET", params, get_system_time=True)
self._assert_rest_result(
result, _("Get snapshot info session error."))
return result.get("data", {})

def rollback_snapshot(self, vol_name, snapshot_name):
url = "/snapshot/rollback"
params = {"snapshotName": snapshot_name,
"volumeName": vol_name
}
result = self.call(url, "POST", params)
self._assert_rest_result(
result, _("Rollback snapshot session error."))

def cancel_rollback_snapshot(self, snapshot_name):
url = "/api/v2/block_service/snapshots"
params = {"name": snapshot_name,
"action": "cancel_rollback"
}
result = self.call(url, "POST", params, get_system_time=True)
self._assert_rest_result(
result, _("Cancel rollback snapshot session error."))
59 changes: 54 additions & 5 deletions Cinder/Pike/fs_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import time

from oslo_log import log as logging
from oslo_service import loopingcall

from cinder import context
from cinder import exception
Expand Down Expand Up @@ -341,9 +342,10 @@ def _get_qos_time_params(zone_flag, time_zone, config_sec,
qos_time_params, is_date_increase = _get_qos_time_params_west_zone(
time_zone, config_sec, cur_date_in_dst_time)
LOG.info("qos time is: %(time)s, is_date_decrease is %(decrease)s, "
"is_date_increase is %(crease)s" % {"time": qos_time_params,
"decrease": is_date_decrease,
"crease": is_date_increase})
"is_date_increase is %(crease)s" %
{"time": qos_time_params,
"decrease": is_date_decrease,
"crease": is_date_increase})
return qos_time_params, is_date_decrease, is_date_increase


Expand Down Expand Up @@ -381,13 +383,14 @@ def _get_diff_time(time_config):
def _convert_start_date(qos, sys_loc_time, configed_none_default):
start_date = constants.QOS_SCHEDULER_KEYS[1]
sys_date_time = time.strftime("%Y-%m-%d", sys_loc_time)
diff_utc_time = time.altzone if time.daylight else time.timezone
if qos.get(start_date):
# Convert the config date to timestamp
cur_date = time.mktime(time.strptime(
sys_date_time, '%Y-%m-%d')) - time.timezone
sys_date_time, '%Y-%m-%d')) - diff_utc_time
try:
config_date = time.mktime(time.strptime(
qos[start_date], '%Y-%m-%d')) - time.timezone
qos[start_date], '%Y-%m-%d')) - diff_utc_time
except Exception as err:
msg = (_("The start date %(date)s is illegal. Reason: %(err)s")
% {"date": qos[start_date], "err": err})
Expand Down Expand Up @@ -504,3 +507,49 @@ def get_volume_specs(client, vol_name):
qos_info[key] = int(value)
vol_info['qos'] = qos_info
return vol_info


def is_snapshot_rollback_available(client, snap_name):
snapshot_info = client.get_snapshot_info_by_name(snap_name)

running_status = snapshot_info.get("running_status")
health_status = snapshot_info.get("health_status")

if running_status not in (
constants.SNAPSHOT_RUNNING_STATUS_ONLINE,
constants.SNAPSHOT_RUNNING_STATUS_ROLLBACKING):
err_msg = (_("The running status %(status)s of snapshot %(name)s.")
% {"status": running_status, "name": snap_name})
LOG.error(err_msg)
raise exception.InvalidSnapshot(reason=err_msg)

if health_status not in (constants.SNAPSHOT_HEALTH_STATS_NORMAL, ):
err_msg = (_("The health status %(status)s of snapshot %(name)s.")
% {"status": running_status, "name": snap_name})
LOG.error(err_msg)
raise exception.InvalidSnapshot(reason=err_msg)

if constants.SNAPSHOT_RUNNING_STATUS_ONLINE == snapshot_info.get(
'running_status'):
return True

return False


def wait_for_condition(func, interval, timeout):
start_time = time.time()

def _inner():
result = func()

if result:
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()
10 changes: 10 additions & 0 deletions Cinder/Queens/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,15 @@
QOS_SUPPORT_SCHEDULE_VERSION = "8.0"
SECONDS_OF_DAY = 24 * 60 * 60
SECONDS_OF_HOUR = 60 * 60
SNAPSHOT_HEALTH_STATUS = (
SNAPSHOT_HEALTH_STATS_NORMAL,
SNAPSHOT_HEALTH_STATS_FAULT) = (1, 2)
SNAPSHOT_RUNNING_STATUS = (
SNAPSHOT_RUNNING_STATUS_ONLINE,
SNAPSHOT_RUNNING_STATUS_OFFLINE,
SNAPSHOT_RUNNING_STATUS_ROLLBACKING) = (27, 28, 44)
SNAPSHOT_ROLLBACK_PROGRESS_FINISH = 100
SNAPSHOT_ROLLBACK_TIMEOUT = 60 * 60 * 24
WAIT_INTERVAL = 10
WEEK_DAYS = ["Sun", "Mon", "Tue", "Wed", "Thur", "Fri", "Sat"]
TIMEZONE = {"Asia/Beijing": "Asia/Shanghai"}
63 changes: 62 additions & 1 deletion Cinder/Queens/dsware.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from cinder.i18n import _
from cinder import interface
from cinder.volume import driver
from cinder.volume.drivers.fusionstorage import constants
from cinder.volume.drivers.fusionstorage import fs_client
from cinder.volume.drivers.fusionstorage import fs_conf
from cinder.volume.drivers.fusionstorage import fs_flow
Expand Down Expand Up @@ -107,7 +108,13 @@
default=[],
help='The ips of FSA node were used to find the target '
'initiator and target ips in ISCSI initialize connection.'
' For example: "target_ips = ip1, ip2"')
' For example: "target_ips = ip1, ip2"'),
cfg.IntOpt('scan_device_timeout',
default=3,
help='scan_device_timeout indicates the waiting time for '
'scanning device disks on the host. It only takes effect'
' on SCSI. Default value is 3, the type is Int, the unit '
'is seconds. For example: "scan_device_timeout = 5"')
]

CONF = cfg.CONF
Expand Down Expand Up @@ -184,8 +191,10 @@ def _get_capacity(self, pool_info):
total = float(pool_info['totalCapacity']) / units.Ki
free = (float(pool_info['totalCapacity']) -
float(pool_info['usedCapacity'])) / units.Ki
provisioned = float(pool_info['usedCapacity']) / units.Ki
pool_capacity['total_capacity_gb'] = total
pool_capacity['free_capacity_gb'] = free
pool_capacity['provisioned_capacity_gb'] = provisioned

return pool_capacity

Expand All @@ -196,6 +205,7 @@ def _update_single_pool_info_status(self, pool_info):
"pool_name": pool_info['poolName'],
"total_capacity_gb": capacity['total_capacity_gb'],
"free_capacity_gb": capacity['free_capacity_gb'],
"provisioned_capacity_gb": capacity['provisioned_capacity_gb'],
"QoS_support": True,
'multiattach': True,
})
Expand Down Expand Up @@ -543,6 +553,52 @@ def retype(self, context, volume, new_type, diff, host):

return True, None

def _rollback_snapshot(self, vol_name, snap_name):
def _snapshot_rollback_finish():
snapshot_info = self.client.get_snapshot_info_by_name(snap_name)
if not snapshot_info:
msg = (_("Failed to get rollback info with snapshot %s.")
% snap_name)
self._raise_exception(msg)

if snapshot_info.get('health_status') not in (
constants.SNAPSHOT_HEALTH_STATS_NORMAL,):
msg = _("The snapshot %s is abnormal.") % snap_name
self._raise_exception(msg)

if (snapshot_info.get('rollback_progress') ==
constants.SNAPSHOT_ROLLBACK_PROGRESS_FINISH or
snapshot_info.get('rollback_endtime')):
LOG.info("Snapshot %s rollback successful.", snap_name)
return True
return False

if fs_utils.is_snapshot_rollback_available(self.client, snap_name):
self.client.rollback_snapshot(vol_name, snap_name)

try:
fs_utils.wait_for_condition(
_snapshot_rollback_finish, constants.WAIT_INTERVAL,
constants.SNAPSHOT_ROLLBACK_TIMEOUT)
except exception.VolumeBackendAPIException:
self.client.cancel_rollback_snapshot(snap_name)
raise

def revert_to_snapshot(self, context, volume, snapshot):
vol_name = self._get_vol_name(volume)
snap_name = self._get_snapshot_name(snapshot)
if not self._check_snapshot_exist(snapshot.volume, snapshot):
msg = _("Snapshot: %(name)s does not exist!"
) % {"name": snap_name}
self._raise_exception(msg)

if not self._check_volume_exist(volume):
msg = _("Volume: %(vol_name)s does not exist!"
) % {'vol_name': vol_name}
self._raise_exception(msg)

self._rollback_snapshot(vol_name, snap_name)

def create_export(self, context, volume, connector):
pass

Expand Down Expand Up @@ -604,6 +660,11 @@ def initialize_connection(self, volume, connector):
vol_wwn = volume_info.get('wwn')
by_id_path = "/dev/disk/by-id/" + "wwn-0x%s" % vol_wwn
properties = {'device_path': by_id_path}
import time
LOG.info("Wait %(t)s second(s) for scanning the target device %(dev)s."
% {"t": self.configuration.scan_device_timeout,
"dev": by_id_path})
time.sleep(self.configuration.scan_device_timeout)
return {'driver_volume_type': 'local',
'data': properties}

Expand Down
Loading

0 comments on commit 02cae27

Please sign in to comment.