Source code for openlmi.storage.LMI_VGStoragePool

# Copyright (C) 2012 Red Hat, Inc.  All rights reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
#
# Authors: Jan Safranek <jsafrane@redhat.com>
# -*- coding: utf-8 -*-
""""
Module for LMI_VGStoragePool class.

LMI_VGStoragePool
-----------------

.. autoclass:: LMI_VGStoragePool
    :members:

"""

from openlmi.storage.DeviceProvider import DeviceProvider
import pywbem
import blivet
import openlmi.common.cmpi_logging as cmpi_logging
from openlmi.storage.SettingHelper import SettingHelper
from openlmi.storage.SettingManager import StorageSetting
import openlmi.storage.util.units as units
import openlmi.storage.util.storage as storage
import math
from openlmi.storage.SettingProvider import SettingProvider

[docs]class LMI_VGStoragePool(DeviceProvider, SettingHelper): """ Provider of LMI_VGStoragePool. """ @cmpi_logging.trace_method
[docs] def __init__(self, *args, **kwargs): super(LMI_VGStoragePool, self).__init__( setting_classname='LMI_LVStorageSetting', *args, **kwargs)
@cmpi_logging.trace_method
[docs] def provides_name(self, object_name): """ Returns True, if this class is provider for given CIM InstanceName. """ if not object_name.has_key('InstanceID'): return False instance_id = object_name['InstanceID'] parts = instance_id.split(":") if len(parts) != 3: return False if parts[0] != "LMI": return False if parts[1] != "VG": return False return True
@cmpi_logging.trace_method
[docs] def provides_device(self, device): """ Returns True, if this class is provider for given Anaconda StorageDevice class. """ if isinstance(device, blivet.devices.LVMVolumeGroupDevice): return True return False
@cmpi_logging.trace_method
[docs] def get_device_for_name(self, object_name): """ Returns Anaconda StorageDevice for given CIM InstanceName or None if no device is found. """ if self.provides_name(object_name): instance_id = object_name['InstanceID'] parts = instance_id.split(":") vgname = parts[2] for vg in self.storage.vgs: if vg.name == vgname: return vg return None
@cmpi_logging.trace_method
[docs] def get_name_for_device(self, device): """ Returns CIM InstanceName for given Anaconda StorageDevice. None if no device is found. """ vgname = device.name name = pywbem.CIMInstanceName('LMI_VGStoragePool', namespace=self.config.namespace, keybindings={ 'InstanceID' : "LMI:VG:" + vgname }) return name
@cmpi_logging.trace_method # pylint: disable-msg=W0221
[docs] def get_instance(self, env, model, device=None): """ Provider implementation of GetInstance intrinsic method. It fills all VGStoragePool properties. """ if not self.provides_name(model): raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, "Wrong keys.") if not device: device = self.get_device_for_name(model) if not device: raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, "Cannot find the VG.") model['Primordial'] = False model['ElementName'] = device.name model['PoolID'] = device.name model['TotalManagedSpace'] = pywbem.Uint64( device.extents * device.peSize * units.MEGABYTE) model['RemainingManagedSpace'] = pywbem.Uint64( device.freeExtents * device.peSize * units.MEGABYTE) model['ExtentSize'] = pywbem.Uint64(device.peSize * units.MEGABYTE) model['TotalExtents'] = pywbem.Uint64(device.extents) model['RemainingExtents'] = pywbem.Uint64(device.freeExtents) model['UUID'] = device.uuid return model
@cmpi_logging.trace_method
[docs] def enum_instances(self, env, model, keys_only): """Enumerate instances. The WBEM operations EnumerateInstances and EnumerateInstanceNames are both mapped to this method. This method is a python generator Keyword arguments: env -- Provider Environment (pycimmb.ProviderEnvironment) model -- A template of the pywbem.CIMInstances to be generated. The properties of the model are already filtered according to the PropertyList from the request. Only properties present in the model need to be given values. If you prefer, you can always set all of the values, and the instance will be filtered for you. keys_only -- A boolean. True if only the key properties should be set on the generated instances. Possible Errors: CIM_ERR_FAILED (some other unspecified error occurred) """ model.path.update({'InstanceID': None}) for device in self.storage.vgs: name = self.get_name_for_device(device) model['InstanceID'] = name['InstanceID'] if keys_only: yield model else: yield self.get_instance(env, model, device)
@cmpi_logging.trace_method
[docs] def cim_method_getsupportedsizes(self, env, object_name, param_elementtype=None, param_goal=None, param_sizes=None): """Implements LMI_VGStoragePool.GetSupportedSizes() """ rval = self.Values.GetSupportedSizes.Use_GetSupportedSizes_instead return (rval, [])
@cmpi_logging.trace_method
[docs] def cim_method_getsupportedsizerange(self, env, object_name, param_minimumvolumesize=None, param_maximumvolumesize=None, param_elementtype=None, param_volumesizedivisor=None, param_goal=None): """Implements LMI_VGStoragePool.GetSupportedSizeRange() param_minimumvolumesize -- The input parameter MinimumVolumeSize (type pywbem.Uint64) The minimum size for a volume/pool in bytes. param_maximumvolumesize -- The input parameter MaximumVolumeSize (type pywbem.Uint64) The maximum size for a volume/pool in bytes. param_elementtype -- The input parameter ElementType (type pywbem.Uint16 self.Values.GetSupportedSizeRange.ElementType) The type of element for which supported size ranges are reported. The Thin Provision values are only supported when the Thin Provisioning Profile is supported; the resulting StorageVolues/LogicalDisk shall have ThinlyPprovisioned set to true. param_volumesizedivisor -- The input parameter VolumeSizeDivisor (type pywbem.Uint64) A volume/pool size must be a multiple of this value which is specified in bytes. param_goal -- The input parameter Goal (type REF (pywbem.CIMInstanceName(classname='CIM_StorageSetting', ...)) The StorageSetting for which supported size ranges should be reported for. Returns a two-tuple containing the return value (type pywbem.Uint32 self.Values.GetSupportedSizeRange) and a list of CIMParameter objects representing the output parameters Output parameters: MinimumVolumeSize -- (type pywbem.Uint64) The minimum size for a volume/pool in bytes. MaximumVolumeSize -- (type pywbem.Uint64) The maximum size for a volume/pool in bytes. VolumeSizeDivisor -- (type pywbem.Uint64) A volume/pool size must be a multiple of this value which is specified in bytes. Possible Errors: CIM_ERR_ACCESS_DENIED CIM_ERR_INVALID_PARAMETER (including missing, duplicate, unrecognized or otherwise incorrect parameters) CIM_ERR_NOT_FOUND (the target CIM Class or instance does not exist in the specified namespace) CIM_ERR_METHOD_NOT_AVAILABLE (the CIM Server is unable to honor the invocation request) CIM_ERR_FAILED (some other unspecified error occurred) """ if not self.provides_name(object_name): raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, "Wrong keys.") device = self.get_device_for_name(object_name) if not device: raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, "Cannot find the VG.") # we support only logical disks for now (should be StorageExtent) etypes = self.Values.GetSupportedSizeRange.ElementType if (param_elementtype and param_elementtype != etypes.Logical_Disk): ret = self.Values.GetSupportedSizeRange.Invalid_Element_Type return (ret, []) # TODO: check Goal setting! extent_size = long(device.peSize * units.MEGABYTE) available_size = long( device.peSize * device.freeExtents * units.MEGABYTE) out_params = [] out_params += [pywbem.CIMParameter('minimumvolumesize', type='uint64', value=pywbem.Uint64(extent_size))] out_params += [pywbem.CIMParameter('maximumvolumesize', type='uint64', value=pywbem.Uint64(available_size))] out_params += [pywbem.CIMParameter('volumesizedivisor', type='uint64', value=pywbem.Uint64(extent_size))] rval = pywbem.Uint32( self.Values.GetSupportedSizeRange.Method_completed_OK) return (rval, out_params)
@cmpi_logging.trace_method def _get_setting_for_device(self, device, setting_provider): """ Return setting for given device """ _id = storage.get_persistent_name(device) setting = self.setting_manager.create_setting( self.setting_classname, StorageSetting.TYPE_CONFIGURATION, setting_provider.create_setting_id(_id), class_to_create=StorageSetting) setting.set_setting(self.get_redundancy(device)) setting['ExtentSize'] = device.peSize * units.MEGABYTE setting['ElementName'] = device.path return setting @cmpi_logging.trace_method
[docs] def enumerate_settings(self, setting_provider): """ This method returns iterable with all instances of LMI_*Setting as Setting instances. """ for lv in self.storage.vgs: yield self._get_setting_for_device(lv, setting_provider)
@cmpi_logging.trace_method
[docs] def get_setting_for_id(self, setting_provider, instance_id): """ Return Setting instance, which corresponds to LMI_*Setting with given InstanceID. Return None if there is no such instance. Subclasses must override this method. """ path = setting_provider.parse_setting_id(instance_id) if not path: return None device = storage.get_device_for_persistent_name(self.storage, path) if not path: return None if not isinstance(device, blivet.devices.LVMVolumeGroupDevice): cmpi_logging.logger.trace_warn( "InstanceID %s is not LVMLogicalVolumeDevice" % instance_id) return None return self._get_setting_for_device(device, setting_provider)
@cmpi_logging.trace_method
[docs] def get_associated_element_name(self, setting_provider, instance_id): """ Return CIMInstanceName of ManagedElement for ElementSettingData association for setting with given ID. Return None if no such ManagedElement exists. """ path = setting_provider.parse_setting_id(instance_id) if not path: return None device = storage.get_device_for_persistent_name(self.storage, path) if not device: return None if not isinstance(device, blivet.devices.LVMVolumeGroupDevice): cmpi_logging.logger.trace_warn( "InstanceID %s is not LVMLogicalVolumeDevice" % instance_id) return None return self.get_name_for_device(device)
@cmpi_logging.trace_method
[docs] def get_supported_setting_properties(self, setting_provider): """ Return hash property_name -> constructor. constructor is a function which takes string argument and returns CIM value. (i.e. pywbem.Uint16 or bool or string etc). This hash will be passed to SettingProvider.__init__ """ return { 'ExtentSize': pywbem.Uint64, 'DataRedundancyGoal': pywbem.Uint16, 'DataRedundancyMax': pywbem.Uint16, 'DataRedundancyMin': pywbem.Uint16, 'ExtentStripeLength' : pywbem.Uint16, 'ExtentStripeLengthMax' : pywbem.Uint16, 'ExtentStripeLengthMin' : pywbem.Uint16, 'NoSinglePointOfFailure' : SettingProvider.string_to_bool, 'PackageRedundancyGoal' : pywbem.Uint16, 'PackageRedundancyMax' : pywbem.Uint16, 'PackageRedundancyMin' : pywbem.Uint16, 'ParityLayout' : pywbem.Uint16, }
@cmpi_logging.trace_method def get_setting_validators(self, setting_provider): return { 'ExtentSize': self._check_extent_size } @cmpi_logging.trace_method def get_setting_ignore(self, setting_provider): return { 'CompressedElement': False, 'CompressionRate': 1, 'InitialSynchronization': 0, 'SpaceLimit': 0, 'ThinProvisionedInitialReserve': 0, 'UseReplicationBuffer': 0, } @cmpi_logging.trace_method def _check_extent_size(self, value): """ Check if the given value is acceptable as VGStorageSetting.ExtentSize. """ # lowest value is 1MB if value < units.MEGABYTE: raise pywbem.CIMError(pywbem.CIM_ERR_FAILED, "Property ExtentSize must be at least 1MiB") # must be power of 2 exp = math.log(value, 2) if math.floor(exp) != exp: raise pywbem.CIMError(pywbem.CIM_ERR_FAILED, "Property ExtentSize must be power of 2") return True @cmpi_logging.trace_method def do_delete_instance(self, device): storage.log_storage_call("DELETE VG", {'device': device}) action = blivet.deviceaction.ActionDestroyDevice(device) storage.do_storage_action(self.storage, [action]) class Values(DeviceProvider.Values): class GetSupportedSizeRange(object): Method_completed_OK = pywbem.Uint32(0) Method_not_supported = pywbem.Uint32(1) Use_GetSupportedSizes_instead = pywbem.Uint32(2) Invalid_Element_Type = pywbem.Uint32(3) class ElementType(object): Storage_Pool = pywbem.Uint16(2) Storage_Volume = pywbem.Uint16(3) Logical_Disk = pywbem.Uint16(4) Thin_Provisioned_Volume = pywbem.Uint16(5) Thin_Provisioned_Logical_Disk = pywbem.Uint16(6) class GetSupportedSizes(object): Method_completed_OK = pywbem.Uint32(0) Method_not_supported = pywbem.Uint32(1) Use_GetSupportedSizes_instead = pywbem.Uint32(2) Invalid_Element_Type = pywbem.Uint32(3) class ElementType(object): Storage_Pool = pywbem.Uint16(2) Storage_Volume = pywbem.Uint16(3) Logical_Disk = pywbem.Uint16(4) Thin_Provisioned_Volume = pywbem.Uint16(5) Thin_Provisioned_Logical_Disk = pywbem.Uint16(6)