-
Notifications
You must be signed in to change notification settings - Fork 29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[GH-241] Unity: adds lun migration support #243
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,12 +17,17 @@ | |
|
||
import logging | ||
|
||
import retryz | ||
|
||
import storops.unity.resource.move_session | ||
import storops.unity.resource.pool | ||
from storops.exception import UnityBaseHasThinCloneError, \ | ||
UnityResourceNotFoundError, UnityCGMemberActionNotSupportError, \ | ||
UnityThinCloneNotAllowedError | ||
UnityThinCloneNotAllowedError, UnityMigrationSourceHasThinCloneError, \ | ||
UnityMigrationTimeoutException | ||
from storops.lib.thinclone_helper import TCHelper | ||
from storops.lib.version import version | ||
from storops.unity import enums | ||
from storops.unity.client import UnityClient | ||
from storops.unity.enums import TieringPolicyEnum, NodeEnum, \ | ||
HostLUNAccessEnum, ThinCloneActionEnum, StorageResourceTypeEnum | ||
|
@@ -353,6 +358,46 @@ def thin_clone(self, name, io_limit_policy=None, description=None): | |
return TCHelper.thin_clone(self._cli, self, name, io_limit_policy, | ||
description) | ||
|
||
def _is_move_session_supported(self, dest): | ||
if self.is_thin_clone: | ||
log.error('Not support move session, source lun is thin clone.') | ||
return False | ||
if self.is_data_reduction_enabled and not dest.is_all_flash: | ||
log.error('Not support move session, source lun is compressed, ' | ||
'but destination pool is not all flash pool.') | ||
return False | ||
return True | ||
|
||
def migrate(self, dest, **kwargs): | ||
if not self._is_move_session_supported(dest): | ||
return False | ||
|
||
interval = kwargs.pop('interval', 5) | ||
timeout = kwargs.pop('timeout', 1800) | ||
|
||
@retryz.retry(timeout=timeout, wait=interval, | ||
on_return=lambda x: not isinstance(x, bool)) | ||
def _do_check_move_session(move_session_id): | ||
move_session = clz.get(self._cli, _id=move_session_id) | ||
if move_session.state == enums.MoveSessionStateEnum.COMPLETED: | ||
return True | ||
if move_session.state in [enums.MoveSessionStateEnum.FAILED, | ||
enums.MoveSessionStateEnum.CANCELLED]: | ||
return False | ||
|
||
clz = storops.unity.resource.move_session.UnityMoveSession | ||
is_compressed = self.is_data_reduction_enabled | ||
|
||
try: | ||
move_session = clz.create(self._cli, self, dest, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What if the lun is in cg? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If lun in cg, REST will return 409 source or dest does not exist error, storops will raise UnityMigrationSourceDestNotExistsError exception. |
||
is_data_reduction_applied=is_compressed) | ||
return _do_check_move_session(move_session.id) | ||
except UnityMigrationSourceHasThinCloneError: | ||
log.error('Not support move session, source lun has thin clone.') | ||
return False | ||
except retryz.RetryTimeoutError: | ||
raise UnityMigrationTimeoutException() | ||
|
||
# `__getstate__` and `__setstate__` are used by Pickle. | ||
def __getstate__(self): | ||
return {'_id': self.get_id(), 'cli': self._cli} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
# Copyright (c) 2015 EMC Corporation. | ||
# 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. | ||
|
||
from __future__ import unicode_literals | ||
|
||
import logging | ||
|
||
from storops.unity.resource import UnityResource, UnityResourceList | ||
|
||
__author__ = 'Yong Huang' | ||
|
||
LOG = logging.getLogger(__name__) | ||
|
||
|
||
class UnityMoveSession(UnityResource): | ||
@classmethod | ||
def create(cls, cli, source_storage_resource, destination_pool, | ||
source_member_lun=None, is_dest_thin=None, | ||
is_data_reduction_applied=None, priority=None): | ||
req_body = cls._compose_move_session_parameter( | ||
cli, source_storage_resource=source_storage_resource, | ||
destination_pool=destination_pool, | ||
source_member_lun=source_member_lun, | ||
is_dest_thin=is_dest_thin, | ||
is_data_reduction_applied=is_data_reduction_applied, | ||
priority=priority) | ||
resp = cli.post(cls().resource_class, **req_body) | ||
resp.raise_if_err() | ||
move_session = cls.get(cli, resp.resource_id) | ||
return move_session | ||
|
||
def modify(self, cli, priority=None): | ||
req_body = self._compose_move_session_parameter(cli, | ||
priority=priority) | ||
resp = self.action('modify', **req_body) | ||
resp.raise_if_err() | ||
return resp | ||
|
||
def cancel(self): | ||
resp = self.action('cancel') | ||
resp.raise_if_err() | ||
return resp | ||
|
||
@staticmethod | ||
def _compose_move_session_parameter(cli, source_storage_resource=None, | ||
destination_pool=None, | ||
source_member_lun=None, | ||
is_dest_thin=None, | ||
is_data_reduction_applied=None, | ||
priority=None): | ||
req_body = cli.make_body( | ||
sourceStorageResource=source_storage_resource, | ||
destinationPool=destination_pool, | ||
sourceMemberLun=source_member_lun, | ||
isDestThin=is_dest_thin, | ||
isDataReductionApplied=is_data_reduction_applied, | ||
priority=priority) | ||
return req_body | ||
|
||
|
||
class UnityMoveSessionList(UnityResourceList): | ||
@classmethod | ||
def get_resource_class(cls): | ||
return UnityMoveSession |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it is with
FAILED
,CANCELLED
orCOMPLETED
, it is completed too. We could return quickly here, or we need to wait until timeout.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, will check FAILED and CANCELLED states.