#!/usr/bin/python # # 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 Synacek from test_base import LogicalFileTestBase import unittest import pywbem import os import stat import shutil import subprocess class TestLogicalFile(LogicalFileTestBase): """ Exhaustive LogicalFile tests. """ def setUp(self): super(TestLogicalFile, self).setUp() self.files = {'data':{'path' : self.testdir + "/data", 'class': 'LMI_DataFile', 'props': {'Readable':True, 'Writeable':False, 'Executable':True, 'SELinuxCurrentContext':'testlf_u:testlf_r:testlf_data_t:s0', 'SELinuxExpectedContext':''}}, 'dir':{'path' : self.testdir + "/dir", 'class': 'LMI_UnixDirectory', 'props': {}}, 'hardlink':{'path' : self.testdir + "/hardlink", 'class': 'LMI_DataFile', 'props': {'Readable':True, 'Writeable':False, 'Executable':True}}, 'symlink':{'path' : self.testdir + "/symlink", 'class': 'LMI_SymbolicLink', 'props': {'SELinuxCurrentContext':'testlf_u:testlf_r:testlf_symlink_t:s0', 'SELinuxExpectedContext':''}}, 'fifo':{'path' : self.testdir + "/fifo", 'class': 'LMI_FIFOPipeFile', 'props': {}}, 'chdev':{'path' : self.testdir + "/chdev", 'class': 'LMI_UnixDeviceFile', 'props': {'DeviceMajor':2, 'DeviceMinor':4}}, 'bldev':{'path' : self.testdir + "/bldev", 'class': 'LMI_UnixDeviceFile', 'props': {'DeviceMajor':3, 'DeviceMinor':5}}, '..':{'path' : os.path.realpath(self.testdir + "/.."), 'class': 'LMI_UnixDirectory', 'props': {}}} self.cop = pywbem.CIMInstanceName(classname='LMI_UnixDirectory', namespace='root/cimv2', keybindings={ 'CSCreationClassName':self.SYSTEM_CLASS_NAME, 'CSName':self.SYSTEM_NAME, 'FSCreationClassName':'LMI_LocalFileSystem', 'FSName':self.fsname, 'CreationClassName':'LMI_UnixDirectory', 'Name':self.testdir }) self._prepare() def tearDown(self): self._cleanup() def _prepare(self): try: os.stat(self.testdir) except OSError: os.makedirs(self.testdir) data_file = self.files['data']['path'] data_props = self.files['data']['props'] f = open(data_file, "w+") f.write("hello") f.close() os.chmod(data_file, 0550) if self.selinux_enabled: labels = data_props['SELinuxCurrentContext'].split(':') out = subprocess.check_output(['chcon', '-h', '-u', labels[0], '-r', labels[1], '-t', labels[2], data_file]) out = subprocess.check_output(['matchpathcon', '-n', data_file]) data_props['SELinuxExpectedContext'] = out[:-1] # remove \n os.mkdir(self.files['dir']['path']) os.link(data_file, self.files['hardlink']['path']) slink_file = self.files['symlink']['path'] slink_props = self.files['symlink']['props'] os.symlink(data_file, slink_file) if self.selinux_enabled: labels = slink_props['SELinuxCurrentContext'].split(':') out = subprocess.check_output(['chcon', '-h', '-u', labels[0], '-r', labels[1], '-t', labels[2], slink_file]) out = subprocess.check_output(['matchpathcon', '-n', slink_file]) slink_props['SELinuxExpectedContext'] = out[:-1] # remove \n os.mkfifo(self.files['fifo']['path']) chdev = self.files['chdev'] chdev_device = os.makedev(chdev['props']['DeviceMajor'], chdev['props']['DeviceMinor']) os.mknod(chdev['path'], 0666 | stat.S_IFCHR, chdev_device) bldev = self.files['bldev'] bldev_device = os.makedev(bldev['props']['DeviceMajor'], bldev['props']['DeviceMinor']) os.mknod(bldev['path'], 0666 | stat.S_IFBLK, bldev_device) def _cleanup(self): shutil.rmtree(self.testdir) def test_lmi_directorycontainsfile(self): # Associators and AssociatorNames for assoc_method in [self.wbemconnection.Associators, self.wbemconnection.AssociatorNames]: assocs = assoc_method(self.cop, AssocClass='LMI_DirectoryContainsFile') self.assertEquals(len(assocs), len(self.files.keys())) for k, f in self.files.iteritems(): # test that the files are actually there and have the correct class name match = filter(lambda a: a['Name'] == f['path'], assocs) self.assertEquals(len(match), 1) self.assertEquals(match[0].classname, f['class']) if not isinstance(match[0], pywbem.CIMInstanceName): # test some selected properties if k == 'data' or k == 'hardlink': self.assertEquals(match[0]['Readable'], f['props']['Readable']) self.assertEquals(match[0]['Writeable'], f['props']['Writeable']) self.assertEquals(match[0]['Executable'], f['props']['Executable']) if k == 'chdev' or k == 'bldev': self.assertEqual(match[0]['DeviceMajor'], str(f['props']['DeviceMajor'])) self.assertEqual(match[0]['DeviceMinor'], str(f['props']['DeviceMinor'])) if k == 'symlink': self.assertEqual(match[0]['TargetFile'], self.files['data']['path']) # test the other side of LMI_DirectoryContainsFile if k != '..': cop_file = pywbem.CIMInstanceName(classname=f['class'], namespace='root/cimv2', keybindings={ 'CSCreationClassName':self.SYSTEM_CLASS_NAME, 'CSName':self.SYSTEM_NAME, 'FSCreationClassName':'LMI_LocalFileSystem', 'FSName':self.fsname, 'CreationClassName':f['class'], 'Name':f['path'] }) assocs_file = assoc_method(cop_file, AssocClass='LMI_DirectoryContainsFile') self.assertEquals(len(assocs_file), 1) self.assertEquals(assocs_file[0].classname, 'LMI_UnixDirectory') self.assertEquals(assocs_file[0]['Name'], self.testdir) # References and ReferenceNames for assoc_method in [self.wbemconnection.References, self.wbemconnection.ReferenceNames]: assocs = assoc_method(self.cop, ResultClass='LMI_DirectoryContainsFile') self.assertEquals(len(assocs), len(self.files.keys())) for k, f in self.files.iteritems(): # test that the files are actually there and have the correct class name match = filter(lambda a: a['PartComponent']['Name'] == f['path'], assocs) self.assertEquals(len(match), 1) match_name = match[0]['PartComponent'] self.assertEquals(match_name.classname, f['class']) # test the other side of LMI_DirectoryContainsFile if k != '..' and k != 'dir': cop_file = pywbem.CIMInstanceName(classname=f['class'], namespace='root/cimv2', keybindings={ 'CSCreationClassName':self.SYSTEM_CLASS_NAME, 'CSName':self.SYSTEM_NAME, 'FSCreationClassName':'LMI_LocalFileSystem', 'FSName':self.fsname, 'CreationClassName':f['class'], 'Name':f['path'] }) assocs_file = assoc_method(cop_file, ResultClass='LMI_DirectoryContainsFile') self.assertEquals(len(assocs_file), 1) file_name = assocs_file[0]['GroupComponent'] self.assertEquals(file_name.classname, 'LMI_UnixDirectory') self.assertEquals(file_name['Name'], self.testdir) def test_lmi_fileidentity(self): # Associators and AssociatorNames for assoc_method in [self.wbemconnection.Associators, self.wbemconnection.AssociatorNames]: assocs = assoc_method(self.cop, AssocClass='LMI_DirectoryContainsFile') self.assertEquals(len(assocs), len(self.files.keys())) for k, f in self.files.iteritems(): match = filter(lambda a: a['Name'] == f['path'], assocs) self.assertEquals(len(match), 1) self.assertEquals(match[0].classname, f['class']) if isinstance(match[0], pywbem.CIMInstanceName): match[0].path = match[0] assocs_ident = assoc_method(match[0].path, AssocClass='LMI_FileIdentity') self.assertEquals(len(assocs_ident), 1) self.assertEquals(assocs_ident[0]['LFName'], f['path']) self.assertEquals(assocs_ident[0]['LFCreationClassName'], f['class']) if not isinstance(match[0], pywbem.CIMInstanceName): if self.selinux_enabled and (k == 'data' or k == 'symlink'): self.assertEquals(assocs_ident[0]['SELinuxCurrentContext'], f['props']['SELinuxCurrentContext']) self.assertEquals(assocs_ident[0]['SELinuxExpectedContext'], f['props']['SELinuxExpectedContext']) cop_ident = pywbem.CIMInstanceName(classname='LMI_UnixFile', namespace='root/cimv2', keybindings={ 'CSCreationClassName':self.SYSTEM_CLASS_NAME, 'CSName':self.SYSTEM_NAME, 'FSCreationClassName':'LMI_LocalFileSystem', 'FSName':self.fsname, 'LFCreationClassName':f['class'], 'LFName':f['path'] }) assocs_ident = assoc_method(cop_ident, AssocClass='LMI_FileIdentity') self.assertEquals(len(assocs_ident), 1) self.assertEquals(assocs_ident[0]['Name'], f['path']) self.assertEquals(assocs_ident[0]['CreationClassName'], f['class']) # References and ReferenceNames for assoc_method in [self.wbemconnection.References, self.wbemconnection.ReferenceNames]: assocs = assoc_method(self.cop, ResultClass='LMI_DirectoryContainsFile') self.assertEquals(len(assocs), len(self.files.keys())) for k, f in self.files.iteritems(): match = filter(lambda a: a['PartComponent']['Name'] == f['path'], assocs) self.assertEquals(len(match), 1) match_name = match[0]['PartComponent'] self.assertEquals(match_name['CreationClassName'], f['class']) assocs_ident = assoc_method(match_name, ResultClass='LMI_FileIdentity') self.assertEquals(len(assocs_ident), 1) ident_name = assocs_ident[0]['SameElement'] self.assertEquals(ident_name['LFName'], f['path']) self.assertEquals(ident_name['LFCreationClassName'], f['class']) cop_ident = pywbem.CIMInstanceName(classname='LMI_UnixFile', namespace='root/cimv2', keybindings={ 'CSCreationClassName':self.SYSTEM_CLASS_NAME, 'CSName':self.SYSTEM_NAME, 'FSCreationClassName':'LMI_LocalFileSystem', 'FSName':self.fsname, 'LFCreationClassName':f['class'], 'LFName':f['path'] }) assocs_ident = assoc_method(cop_ident, ResultClass='LMI_FileIdentity') self.assertEquals(len(assocs_ident), 1) ident_name = assocs_ident[0]['SystemElement'] self.assertEquals(ident_name['Name'], f['path']) self.assertEquals(ident_name['CreationClassName'], f['class']) def test_lmi_rootdirectory(self): # Associators and AssociatorNames cop = self.cop.copy() cop.keybindings['Name'] = '/' for assoc_method in [self.wbemconnection.Associators, self.wbemconnection.AssociatorNames]: assocs = assoc_method(cop, AssocClass='LMI_RootDirectory') self.assertEquals(len(assocs), 1) system = assocs[0] self.assertEquals(system['CreationClassName'], self.SYSTEM_CLASS_NAME) self.assertEquals(system['Name'], self.SYSTEM_NAME) if isinstance(system, pywbem.CIMInstanceName): system.path = system assocs = self.wbemconnection.Associators(system.path, AssocClass='LMI_RootDirectory') self.assertEquals(len(assocs), 1) self.assertEquals(assocs[0]['Name'], '/') # References and ReferenceNames for assoc_method in [self.wbemconnection.References, self.wbemconnection.ReferenceNames]: assocs = assoc_method(cop, ResultClass='LMI_RootDirectory') self.assertEquals(len(assocs), 1) system = assocs[0]['GroupComponent'] self.assertEquals(system['CreationClassName'], self.SYSTEM_CLASS_NAME) self.assertEquals(system['Name'], self.SYSTEM_NAME) assocs = self.wbemconnection.References(system, ResultClass='LMI_RootDirectory') self.assertEquals(len(assocs), 1) self.assertEquals(assocs[0]['PartComponent']['Name'], '/') def test_mkdir(self): def mkdir(path): cop = self.cop.copy() cop['Name'] = path inst = pywbem.CIMInstance('LMI_UnixDirectory', cop.keybindings) self.wbemconnection.CreateInstance(inst) try: mkdir(self.testdir + '/mkdir-test') except pywbem.CIMError as pe: self.fail(pe[1]) self.assertRaises(pywbem.CIMError, mkdir, '/cant/create/me') def test_rmdir(self): def rmdir(path): cop = self.cop.copy() cop['Name'] = path inst = pywbem.CIMInstance('LMI_UnixDirectory', cop.keybindings) self.wbemconnection.DeleteInstance(cop) try: rmdir(self.files['dir']['path']) except pywbem.CIMError as pe: self.fail(pe[1]) self.assertRaises(pywbem.CIMError, rmdir, '/cant/remove/me') def _test_missing_or_wrong_properties(self, is_unixfile): testfile = self.files['data'] if is_unixfile: prefix = 'LF' clsname = 'LMI_UnixFile' else: prefix = '' clsname = 'LMI_DataFile' cop = pywbem.CIMInstanceName(classname=clsname, namespace='root/cimv2', keybindings={}) prop = 'CSCreationClassName' self.assertRaisesRegexp(pywbem.CIMError, '%s is empty' % prop, self.wbemconnection.GetInstance, cop) cop.keybindings[prop] = 'BadClass' self.assertRaisesRegexp(pywbem.CIMError, 'Wrong %s' % prop, self.wbemconnection.GetInstance, cop) cop.keybindings[prop] = self.SYSTEM_CLASS_NAME prop = 'CSName' self.assertRaisesRegexp(pywbem.CIMError, '%s is empty' % prop, self.wbemconnection.GetInstance, cop) cop.keybindings[prop] = 'BadClass' self.assertRaisesRegexp(pywbem.CIMError, 'Wrong %s' % prop, self.wbemconnection.GetInstance, cop) cop.keybindings[prop] = self.SYSTEM_NAME prop = prefix + 'CreationClassName' self.assertRaisesRegexp(pywbem.CIMError, '%s is empty' % prop, self.wbemconnection.GetInstance, cop) cop.keybindings[prop] = testfile['class'] prop = prefix + 'Name' cop.keybindings[prop] = self.files['dir']['path'] if is_unixfile: self.assertRaisesRegexp(pywbem.CIMError, 'LFCreationClassName doesn\'t match', self.wbemconnection.GetInstance, cop) cop.keybindings[prop] = testfile['path'] prop = 'FSCreationClassName' self.assertRaisesRegexp(pywbem.CIMError, '%s is empty' % prop, self.wbemconnection.GetInstance, cop) cop.keybindings[prop] = 'BadFS' self.assertRaisesRegexp(pywbem.CIMError, 'Wrong %s' % prop, self.wbemconnection.GetInstance, cop) cop.keybindings[prop] = 'LMI_LocalFileSystem' prop = 'FSName' self.assertRaisesRegexp(pywbem.CIMError, '%s is empty' % prop, self.wbemconnection.GetInstance, cop) cop.keybindings[prop] = 'BadFSName' self.assertRaisesRegexp(pywbem.CIMError, 'Wrong %s' % prop, self.wbemconnection.GetInstance, cop) cop.keybindings[prop] = self.fsname # finally, test GetInstance on the correct object path try: self.wbemconnection.GetInstance(cop) except pywbem.CIMError as pe: self.fail(pe[1]) def test_unixfile_missing_or_wrong_properties(self): self._test_missing_or_wrong_properties(True) def test_logicalfile_missing_or_wrong_properties(self): self._test_missing_or_wrong_properties(False) if __name__ == '__main__': unittest.main()