Source code for openlmi.storage.LocalFileSystemProvider

# Copyright (C) 2013 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 LocalFileSystemProvider.

LocalFileSystemProvider
-----------------------

.. autoclass:: LocalFileSystemProvider
    :members:

"""

import pywbem
from openlmi.storage.FormatProvider import FormatProvider
from openlmi.storage.SettingHelper import SettingHelper
from openlmi.storage.SettingManager import Setting
from openlmi.storage.SettingProvider import SettingProvider
import openlmi.common.cmpi_logging as cmpi_logging
from openlmi.storage.util import storage
import os

[docs]class LocalFileSystemProvider(FormatProvider, SettingHelper): """ Abstract provider for local filesystems. Each provider must have .device_type property, which represents blivet.formats.<DeviceFormat child>.type of format it represents. """ @cmpi_logging.trace_method
[docs] def __init__(self, *args, **kwargs): super(LocalFileSystemProvider, self).__init__(*args, **kwargs) vals = LocalFileSystemProvider.Values self.fs_settings = { 'ext2' : { 'ActualFileSystemType': vals.ActualFileSystemType.EXT2, 'DataExtentsSharing': vals.DataExtentsSharing.No_Sharing, 'FilenameCaseAttributes': vals.FilenameCaseAttributes.Case_sensitive, 'ObjectTypes': [ vals.ObjectTypes.inodes, vals.ObjectTypes.files, vals.ObjectTypes.files_directories, ], 'NumberOfObjectsMin': [ pywbem.Uint64(0), pywbem.Uint64(0), pywbem.Uint64(0), ], 'NumberOfObjectsMax': [ pywbem.Uint64(2 ** 32 - 1), # nr. of inodes pywbem.Uint64(10 ** 18), # nr. of files pywbem.Uint64(0), # nr. of files in dir. ], 'NumberOfObjects': [ pywbem.Uint64(0), pywbem.Uint64(0), pywbem.Uint64(0), ], 'ObjectSize': [ pywbem.Uint64(256), # inode size pywbem.Uint64(0), # file size pywbem.Uint64(0), # file size in directory ], 'ObjectSizeMin': [ pywbem.Uint64(128), # inode size pywbem.Uint64(0), # file size pywbem.Uint64(0), # file size in directory ], 'ObjectSizeMax': [ pywbem.Uint64(4096), # inode size pywbem.Uint64(0), # file size pywbem.Uint64(0), # file size in directory ], 'FilenameFormats': [ vals.FilenameFormats.Unix ], 'FilenameLengthMax': [ pywbem.Uint64(255), ], 'PersistenceTypes': [ vals.PersistenceTypes.Persistent] }, 'ext3' : { 'ActualFileSystemType': vals.ActualFileSystemType.EXT3, 'DataExtentsSharing': vals.DataExtentsSharing.No_Sharing, 'FilenameCaseAttributes': vals.FilenameCaseAttributes.Case_sensitive, 'ObjectTypes': [ vals.ObjectTypes.inodes, vals.ObjectTypes.files, vals.ObjectTypes.files_directories, ], 'NumberOfObjectsMin': [ pywbem.Uint64(0), pywbem.Uint64(0), pywbem.Uint64(0), ], 'NumberOfObjectsMax': [ pywbem.Uint64(2 ** 32 - 1), # nr.of inodes pywbem.Uint64(2 ** 32 - 1), # nr. of files pywbem.Uint64(0), ], 'NumberOfObjects': [ pywbem.Uint64(0), # nr.of inodes pywbem.Uint64(0), # nr. of files pywbem.Uint64(0), ], 'ObjectSize': [ pywbem.Uint64(256), # inode size pywbem.Uint64(0), # file size pywbem.Uint64(0), ], 'ObjectSizeMin': [ pywbem.Uint64(128), # inode size pywbem.Uint64(0), # file size pywbem.Uint64(0), ], 'ObjectSizeMax': [ pywbem.Uint64(4096), # inode size pywbem.Uint64(0), # file size pywbem.Uint64(0), ], 'FilenameFormats': [ vals.FilenameFormats.Unix ], 'FilenameLengthMax': [ pywbem.Uint64(255), ], 'PersistenceTypes': [ vals.PersistenceTypes.Persistent] }, 'ext4' : { 'ActualFileSystemType': vals.ActualFileSystemType.EXT4, 'DataExtentsSharing': vals.DataExtentsSharing.No_Sharing, 'FilenameCaseAttributes': vals.FilenameCaseAttributes.Case_sensitive, 'ObjectTypes': [ vals.ObjectTypes.inodes, vals.ObjectTypes.files, vals.ObjectTypes.files_directories, ], 'NumberOfObjectsMin': [ pywbem.Uint64(0), pywbem.Uint64(0), pywbem.Uint64(0), ], 'NumberOfObjectsMax': [ pywbem.Uint64(2 ** 32 - 1), # nr.of inodes pywbem.Uint64(2 ** 32 - 1), # nr. of files pywbem.Uint64(0), ], 'NumberOfObjects': [ pywbem.Uint64(0), pywbem.Uint64(0), pywbem.Uint64(0), ], 'ObjectSize': [ pywbem.Uint64(256), # inode size pywbem.Uint64(0), # file size pywbem.Uint64(0), ], 'ObjectSizeMin': [ pywbem.Uint64(128), # inode size pywbem.Uint64(0), # file size pywbem.Uint64(0), ], 'ObjectSizeMax': [ pywbem.Uint64(4096), # inode size pywbem.Uint64(0), # file size pywbem.Uint64(0), ], 'FilenameFormats': [ vals.FilenameFormats.Unix ], 'FilenameLengthMax': [ pywbem.Uint64(255), ], 'PersistenceTypes': [ vals.PersistenceTypes.Persistent] }, 'btrfs' : { 'ActualFileSystemType': vals.ActualFileSystemType.BTRFS, 'DataExtentsSharing': vals.DataExtentsSharing.No_Sharing, 'FilenameCaseAttributes': vals.FilenameCaseAttributes.Case_sensitive, 'ObjectTypes': [ vals.ObjectTypes.inodes, vals.ObjectTypes.files, vals.ObjectTypes.files_directories, ], 'NumberOfObjectsMin': [ pywbem.Uint64(0), pywbem.Uint64(0), pywbem.Uint64(0), ], 'NumberOfObjectsMax': [ pywbem.Uint64(2 ** 64 - 1), # nr.of inodes pywbem.Uint64(2 ** 64 - 1), # nr. of files pywbem.Uint64(0), ], 'NumberOfObjects': [ pywbem.Uint64(0), pywbem.Uint64(0), pywbem.Uint64(0), ], 'ObjectSize': [ pywbem.Uint64(0), # inode size pywbem.Uint64(0), # file size pywbem.Uint64(0), ], 'ObjectSizeMin': [ pywbem.Uint64(128), # inode size pywbem.Uint64(0), # file size pywbem.Uint64(0), ], 'ObjectSizeMax': [ pywbem.Uint64(4096), # inode size pywbem.Uint64(8 * (2 ** 60)), # file size 8 EiB pywbem.Uint64(0), ], 'FilenameFormats': [ vals.FilenameFormats.Unix ], 'FilenameLengthMax': [ pywbem.Uint64(255), ], 'PersistenceTypes': [ vals.PersistenceTypes.Persistent] }, 'xfs' : { 'ActualFileSystemType': vals.ActualFileSystemType.XFS, 'DataExtentsSharing': vals.DataExtentsSharing.No_Sharing, 'FilenameCaseAttributes': vals.FilenameCaseAttributes.Case_sensitive, 'ObjectTypes': [ vals.ObjectTypes.inodes, vals.ObjectTypes.files, vals.ObjectTypes.files_directories, ], 'NumberOfObjectsMin': [ pywbem.Uint64(0), pywbem.Uint64(0), pywbem.Uint64(0), ], 'NumberOfObjectsMax': [ pywbem.Uint64(2 ** 64 - 1), # nr.of inodes pywbem.Uint64(2 ** 64 - 1), # nr of files pywbem.Uint64(0), ], 'NumberOfObjects': [ pywbem.Uint64(0), pywbem.Uint64(0), pywbem.Uint64(0), ], 'ObjectSize': [ pywbem.Uint64(0), # inode size pywbem.Uint64(0), # file size pywbem.Uint64(0), ], 'ObjectSizeMin': [ pywbem.Uint64(128), # inode size pywbem.Uint64(0), # file size pywbem.Uint64(0), ], 'ObjectSizeMax': [ pywbem.Uint64(4096), # inode size pywbem.Uint64(8 * (2 ** 60) - 1), # file size 8 EiB-1 pywbem.Uint64(0), ], 'FilenameFormats': [ vals.FilenameFormats.Unix ], 'FilenameLengthMax': [ pywbem.Uint64(255), ], 'PersistenceTypes': [ vals.PersistenceTypes.Persistent] }, }
@cmpi_logging.trace_method # pylint: disable-msg=W0221
[docs] def get_instance(self, env, model, fmt=None): """ Get instance. Subclasses should override this method, the default implementation just check if the instance exists. """ if not fmt: (device, fmt) = self.get_format_for_name(model) else: device = self.storage.devicetree.getDeviceByPath(fmt.device) if not fmt: raise pywbem.CIMError(pywbem.CIM_ERR_NOT_FOUND, "Cannot find the format.") model['FileSystemType'] = fmt.name model['CaseSensitive'] = True model['CasePreserved'] = True model['PersistenceType'] = self.Values.PersistenceType.Persistent model['ElementName'] = fmt.device model['IsFixedSize'] = (fmt.resizable == False) uuid = self.get_uuid(device, fmt) if uuid: model['UUID'] = uuid if fmt.label: model['ElementName'] = fmt.label if fmt.mountpoint: model['Root'] = fmt.mountpoint # TODO: this should be provided by Blivet, see bug #915201 stat = os.statvfs(fmt.mountpoint) model['BlockSize'] = pywbem.Uint64(stat.f_bsize) model['FileSystemSize'] = pywbem.Uint64( stat.f_blocks * stat.f_frsize) model['AvailableSpace'] = pywbem.Uint64( stat.f_bavail * stat.f_bsize) model['ReadOnly'] = (stat.f_flag & os.ST_RDONLY) > 0 model['MaxFileNameLength'] = pywbem.Uint32(stat.f_namemax) return model
@cmpi_logging.trace_method def _get_setting_for_format(self, setting_provider, fmt): """ Return Setting for given format. """ # Table of filesystems with Setting values = self.fs_settings.get(fmt.type, None) if values: # yes, we should create Setting for this FS setting = self.setting_manager.create_setting( setting_provider.setting_classname, Setting.TYPE_CONFIGURATION, setting_provider.create_setting_id(fmt.device)) if fmt.mountpoint: # Fill in current filesystem setting. # Copy the values dictionary, we are modifying it. values = values.copy() # TODO: this should be provided by Blivet, see bug #915201 stat = os.statvfs(fmt.mountpoint) # [nr. of inodes, nr. of files, nr. of files in a directory] values['NumberOfObjects'] = [stat.f_files, stat.f_files, 0] values['FilenameLengthMax'] = [stat.f_namemax] for (key, value) in values.iteritems(): setting[key] = str(value) return setting return None @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 device in self.storage.devices: if self.provides_format(device, device.format): setting = self._get_setting_for_format( setting_provider, device.format) if setting: yield setting
@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. """ 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 device.format: return None return self._get_setting_for_format(setting_provider, device.format)
@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 fmt = device.format provider = self.provider_manager.get_provider_for_format(device, fmt) return provider.get_name_for_format(device, fmt)
@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 { 'ActualFileSystemType': pywbem.Uint16, 'DataExtentsSharing': pywbem.Uint16, 'FilenameCaseAttributes': pywbem.Uint16, 'ObjectTypes' : SettingProvider.string_to_uint16_array, 'NumberOfObjectsMin' : SettingProvider.string_to_uint64_array, 'NumberOfObjectsMax' : SettingProvider.string_to_uint64_array, 'NumberOfObjects' : SettingProvider.string_to_uint64_array, 'ObjectSize' : SettingProvider.string_to_uint64_array, 'ObjectSizeMin' : SettingProvider.string_to_uint64_array, 'ObjectSizeMax' : SettingProvider.string_to_uint64_array, 'PersistenceTypes' : SettingProvider.string_to_uint16_array, 'FilenameFormats' : SettingProvider.string_to_uint16_array, 'FilenameLengthMax' : SettingProvider.string_to_uint16_array, }
@cmpi_logging.trace_method def get_setting_ignore(self, setting_provider): return { 'CopyTagret': 0, } class Values(FormatProvider.Values): class PersistenceType(object): Unknown = pywbem.Uint16(0) Other = pywbem.Uint16(1) Persistent = pywbem.Uint16(2) Temporary = pywbem.Uint16(3) External = pywbem.Uint16(4) class ActualFileSystemType(object): Unknown = pywbem.Uint16(0) UFS = pywbem.Uint16(2) HFS = pywbem.Uint16(3) FAT = pywbem.Uint16(4) FAT16 = pywbem.Uint16(5) FAT32 = pywbem.Uint16(6) NTFS4 = pywbem.Uint16(7) NTFS5 = pywbem.Uint16(8) XFS = pywbem.Uint16(9) AFS = pywbem.Uint16(10) EXT2 = pywbem.Uint16(11) EXT3 = pywbem.Uint16(12) REISERFS = pywbem.Uint16(13) # DMTF_Reserved = .. EXT4 = pywbem.Uint16(0x8001) BTRFS = pywbem.Uint16(0x8002) JFS = pywbem.Uint16(0x8003) TMPFS = pywbem.Uint16(0x8004) VFAT = pywbem.Uint16(0x8005) class FilenameCaseAttributes(object): Unknown = pywbem.Uint16(0) Case_sensitive = pywbem.Uint16(1) Case_forced_to_upper_case = pywbem.Uint16(2) Case_forced_to_lower_case = pywbem.Uint16(3) Case_indifferent_but_lost = pywbem.Uint16(4) Case_indifferent_but_preserved = pywbem.Uint16(5) # DMTF_Reserved = .. # Vendor_Defined = 0x8000.. class ObjectTypes(object): inodes = pywbem.Uint16(2) files = pywbem.Uint16(3) directories = pywbem.Uint16(4) links = pywbem.Uint16(5) devices = pywbem.Uint16(6) files_directories = pywbem.Uint16(7) Blocks = pywbem.Uint16(8) # DMTF_Reserved = .. # Vendor_Defined = 0x8000.. class PersistenceTypes(object): Unknown = pywbem.Uint16(0) Other = pywbem.Uint16(1) Persistent = pywbem.Uint16(2) Temporary = pywbem.Uint16(3) External = pywbem.Uint16(4) # DMTF_Reserved = 5.. class DataExtentsSharing(object): Unknown = pywbem.Uint16(0) No_Sharing = pywbem.Uint16(1) Sharing_Possible_Optional = pywbem.Uint16(2) Sharing_Enforced = pywbem.Uint16(3) # DMTF_Reserved = .. # Vendor_Defined = 0x8000.. class FilenameFormats(object): DOS8_3 = pywbem.Uint16(1) Unix = pywbem.Uint16(2) VMS = pywbem.Uint16(3) Windows_LongNames = pywbem.Uint16(4) # DMTF_Reserved = .. # Vendor_Defined = 0x8000..