abd97bb2eb
Try to leverage cache software, such as Open CAS, use high performance disk or persistent memory as the cache in compute node locally for low performance volume that allocated by cinder from remote backend storage. open-cas: https://open-cas.github.io/ Nova Spec: https://review.opendev.org/#/c/689070/ Cinder Spec: https://review.opendev.org/#/c/684556/ Change-Id: Ib120047a65ecbb4ae0f060640d59f3f759a1cade Signed-off-by: Liang Fang <liang.a.fang@intel.com>
104 lines
3.3 KiB
Python
104 lines
3.3 KiB
Python
# 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 abc
|
|
|
|
from oslo_log import log as logging
|
|
from oslo_utils import importutils
|
|
|
|
from os_brick import exception
|
|
from os_brick.i18n import _
|
|
|
|
|
|
LOG = logging.getLogger(__name__)
|
|
|
|
CACHE_ENGINE_TO_CACHE_CLASS_MAP = {
|
|
"opencas": 'os_brick.caches.opencas.OpenCASEngine',
|
|
}
|
|
|
|
|
|
class CacheEngineBase(object, metaclass=abc.ABCMeta):
|
|
def __init__(self, **kwargs):
|
|
self._root_helper = kwargs.get('root_helper')
|
|
|
|
@abc.abstractmethod
|
|
def is_engine_ready(self, **kwargs):
|
|
return
|
|
|
|
@abc.abstractmethod
|
|
def attach_volume(self, **kwargs):
|
|
return
|
|
|
|
@abc.abstractmethod
|
|
def detach_volume(self, **kwargs):
|
|
return
|
|
|
|
|
|
class CacheManager():
|
|
"""Cache manager for volumes.
|
|
|
|
This CacheManager uses cache engines to do volume cache.
|
|
"""
|
|
def __init__(self, root_helper, connection_info,
|
|
*args, **kwargs):
|
|
|
|
data = connection_info['data']
|
|
if not data.get('device_path'):
|
|
volume_id = data.get('volume_id') or connection_info.get('serial')
|
|
raise exception.VolumeLocalCacheNotSupported(
|
|
volume_id=volume_id,
|
|
volume_type=connection_info.get('driver_volume_type'))
|
|
|
|
self.ori_device_path = data.get('device_path')
|
|
if not data.get('cacheable'):
|
|
self.cacheable = False
|
|
return
|
|
|
|
self.cacheable = True
|
|
self.root_helper = root_helper
|
|
self.engine_name = kwargs.get('cache_name')
|
|
self.args = args
|
|
self.kwargs = kwargs
|
|
self.kwargs["root_helper"] = root_helper
|
|
self.kwargs["dev_path"] = data.get('device_path')
|
|
self.engine = self._get_engine(self.engine_name, **self.kwargs)
|
|
|
|
def _get_engine(self, engine_name, **kwargs):
|
|
eng_cls_path = CACHE_ENGINE_TO_CACHE_CLASS_MAP.get(engine_name)
|
|
if eng_cls_path:
|
|
engine_cls = importutils.import_class(eng_cls_path)
|
|
eng = engine_cls(**kwargs)
|
|
if eng.is_engine_ready():
|
|
return eng
|
|
|
|
raise exception.Invalid(_("No valid cache engine"))
|
|
|
|
def attach_volume(self):
|
|
"""setup the cache when attaching volume."""
|
|
if not self.cacheable:
|
|
return self.ori_device_path
|
|
|
|
LOG.debug("volume before cached: %s", self.kwargs.get('dev_path'))
|
|
emulated_disk = self.engine.attach_volume(**self.kwargs)
|
|
LOG.debug("volume after cached: %s", emulated_disk)
|
|
return emulated_disk
|
|
|
|
def detach_volume(self):
|
|
"""Release the cache on detaching volume."""
|
|
if not self.cacheable:
|
|
return self.ori_device_path
|
|
|
|
LOG.debug("volume before detach: %s", self.kwargs.get('dev_path'))
|
|
ori_disk = self.engine.detach_volume(**self.kwargs)
|
|
LOG.debug("volume after detach: %s", ori_disk)
|
|
return ori_disk
|