def getMetaData(self): if self.packageControlFile: # Already done return logger.info(u"Getting meta data from package '%s'" % self.packageFile) try: if not os.path.exists(self.tmpUnpackDir): os.mkdir(self.tmpUnpackDir) os.chmod(self.tmpUnpackDir, 0o700) metaDataTmpDir = os.path.join(self.tmpUnpackDir, u'OPSI') archive = Archive(self.packageFile) logger.debug(u"Extracting meta data from package '%s' to: '%s'" % (self.packageFile, metaDataTmpDir)) archive.extract(targetPath=metaDataTmpDir, patterns=[u"OPSI*"]) metadataArchives = [] for f in os.listdir(metaDataTmpDir): if not f.endswith( (u'.cpio.gz', u'.tar.gz', u'.cpio', u'.tar')): logger.warning(u"Unknown content in archive: %s" % f) continue logger.debug(u"Metadata archive found: %s" % f) metadataArchives.append(f) if not metadataArchives: raise ValueError(u"No metadata archive found") if len(metadataArchives) > 2: raise ValueError(u"More than two metadata archives found") # Sorting to unpack custom version metadata at last metadataArchives.sort() for metadataArchive in metadataArchives: archive = Archive(os.path.join(metaDataTmpDir, metadataArchive)) archive.extract(targetPath=metaDataTmpDir) packageControlFile = os.path.join(metaDataTmpDir, u'control') if not os.path.exists(packageControlFile): raise IOError( u"No control file found in package metadata archives") self.packageControlFile = PackageControlFile(packageControlFile) self.packageControlFile.parse() except Exception as e: logger.logException(e) self.cleanup() raise RuntimeError( u"Failed to get metadata from package '%s': %s" % (self.packageFile, e)) logger.debug(u"Got meta data from package '%s'" % self.packageFile) return self.packageControlFile
def pack(self, progressSubject=None): # Create temporary directory if os.path.exists(self.tmpPackDir): shutil.rmtree(self.tmpPackDir) os.mkdir(self.tmpPackDir) archives = [] diskusage = 0 dirs = [u'CLIENT_DATA', u'SERVER_DATA', u'OPSI'] try: if self.customName: found = False for i, currentDir in enumerate(dirs): customDir = u"%s.%s" % (currentDir, self.customName) if os.path.exists( os.path.join(self.packageSourceDir, customDir)): found = True if self.customOnly: dirs[i] = customDir else: dirs.append(customDir) if not found: raise RuntimeError(u"No custom dirs found for '%s'" % self.customName) # Try to define diskusage from Sourcedirectory to prevent a override from cpio sizelimit. for d in dirs: if not os.path.exists(os.path.join(self.packageSourceDir, d)) and d != u'OPSI': logger.info(u"Directory '%s' does not exist" % os.path.join(self.packageSourceDir, d)) continue fileList = findFiles(os.path.join(self.packageSourceDir, d), excludeDir=EXCLUDE_DIRS_ON_PACK_REGEX, excludeFile=EXCLUDE_FILES_ON_PACK_REGEX, followLinks=self.dereference) if fileList: for f in fileList: diskusage = diskusage + os.path.getsize( os.path.join(self.packageSourceDir, d, f)) if diskusage >= 2147483648: logger.info( u"Switching to tar format, because sourcefiles overrides cpio sizelimit." ) self.format = u'tar' for d in dirs: if not os.path.exists(os.path.join(self.packageSourceDir, d)) and d != u'OPSI': logger.info(u"Directory '%s' does not exist" % os.path.join(self.packageSourceDir, d)) continue fileList = findFiles(os.path.join(self.packageSourceDir, d), excludeDir=EXCLUDE_DIRS_ON_PACK_REGEX, excludeFile=EXCLUDE_FILES_ON_PACK_REGEX, followLinks=self.dereference) if d.startswith(u'SERVER_DATA'): # Never change permissions of existing directories in / tmp = [] for f in fileList: if f.find(os.sep) == -1: logger.info(u"Skipping dir '%s'" % f) continue tmp.append(f) fileList = tmp if not fileList: logger.notice(u"Skipping empty dir '%s'" % os.path.join(self.packageSourceDir, d)) continue filename = os.path.join(self.tmpPackDir, u'%s.%s' % (d, self.format)) if self.compression == 'gzip': filename += u'.gz' elif self.compression == 'bzip2': filename += u'.bz2' archive = Archive(filename, format=self.format, compression=self.compression, progressSubject=progressSubject) if progressSubject: progressSubject.reset() progressSubject.setMessage( u'Creating archive %s' % os.path.basename(archive.getFilename())) archive.create(fileList=fileList, baseDir=os.path.join(self.packageSourceDir, d), dereference=self.dereference) archives.append(filename) archive = Archive(self.packageFile, format=self.format, compression=None, progressSubject=progressSubject) if progressSubject: progressSubject.reset() progressSubject.setMessage( u'Creating archive %s' % os.path.basename(archive.getFilename())) archive.create(fileList=archives, baseDir=self.tmpPackDir) except Exception as e: self.cleanup() raise RuntimeError(u"Failed to create package '%s': %s" % (self.packageFile, e))
def extractData(self): logger.info(u"Extracting data from package '%s'" % self.packageFile) try: if not self.packageControlFile: raise ValueError(u"Metadata not present") if not self.clientDataDir: raise ValueError(u"Client data dir not set") self.clientDataFiles = [] archive = Archive(self.packageFile) logger.info(u"Extracting data from package '%s' to: '%s'" % (self.packageFile, self.tmpUnpackDir)) archive.extract(targetPath=self.tmpUnpackDir, patterns=[u"CLIENT_DATA*", u"SERVER_DATA*"]) clientDataArchives = [] serverDataArchives = [] for f in os.listdir(self.tmpUnpackDir): if f.startswith('OPSI'): continue if not f.endswith( (u'.cpio.gz', u'.tar.gz', u'.cpio', u'.tar')): logger.warning(u"Unknown content in archive: %s" % f) continue if f.startswith('CLIENT_DATA'): logger.debug(u"Client-data archive found: %s" % f) clientDataArchives.append(f) elif f.startswith('SERVER_DATA'): logger.debug(u"Server-data archive found: %s" % f) serverDataArchives.append(f) if not clientDataArchives: logger.warning(u"No client-data archive found") if len(clientDataArchives) > 2: raise ValueError(u"More than two client-data archives found") if len(serverDataArchives) > 2: raise ValueError(u"More than two server-data archives found") # Sorting to unpack custom version data at last def psort(name): return re.sub(r'(\.tar|\.tar\.gz|\.cpio|\.cpio\.gz)$', '', name) clientDataArchives = sorted(clientDataArchives, key=psort) serverDataArchives = sorted(serverDataArchives, key=psort) for serverDataArchive in serverDataArchives: archiveFile = os.path.join(self.tmpUnpackDir, serverDataArchive) logger.info(u"Extracting server-data archive '%s' to '/'" % archiveFile) archive = Archive(archiveFile) archive.extract(targetPath=u'/') productClientDataDir = self.getProductClientDataDir() if not os.path.exists(productClientDataDir): os.mkdir(productClientDataDir) os.chmod(productClientDataDir, 0o2770) for clientDataArchive in clientDataArchives: archiveFile = os.path.join(self.tmpUnpackDir, clientDataArchive) logger.info(u"Extracting client-data archive '%s' to '%s'" % (archiveFile, productClientDataDir)) archive = Archive(archiveFile) archive.extract(targetPath=productClientDataDir) logger.debug(u"Finished extracting data from package") except Exception as e: self.cleanup() raise RuntimeError( u"Failed to extract data from package '%s': %s" % (self.packageFile, e))
def unpackSource(self, destinationDir=u'.', newProductId=None, progressSubject=None): logger.info(u"Extracting package source from '%s'" % self.packageFile) if progressSubject: progressSubject.setMessage( _(u"Extracting package source from '%s'") % self.packageFile) try: destinationDir = forceFilename(destinationDir) if newProductId: newProductId = forceUnicode(newProductId) archive = Archive(filename=self.packageFile, progressSubject=progressSubject) logger.debug(u"Extracting source from package '%s' to: '%s'" % (self.packageFile, destinationDir)) if progressSubject: progressSubject.setMessage(_(u'Extracting archives')) archive.extract(targetPath=self.tmpUnpackDir) for f in os.listdir(self.tmpUnpackDir): logger.info(u"Processing file '%s'" % f) archiveName = u'' if f.endswith('.cpio.gz'): archiveName = f[:-8] elif f.endswith('.cpio'): archiveName = f[:-5] elif f.endswith('.tar.gz'): archiveName = f[:-7] elif f.endswith('.tar'): archiveName = f[:-4] elif f.startswith('OPSI'): continue else: logger.warning(u"Unknown content in archive: %s" % f) continue archive = Archive(filename=os.path.join(self.tmpUnpackDir, f), progressSubject=progressSubject) if progressSubject: progressSubject.setMessage( _(u'Extracting archive %s') % archiveName) archive.extract( targetPath=os.path.join(destinationDir, archiveName)) if newProductId: self.getMetaData() product = self.packageControlFile.getProduct() for scriptName in (u'setupScript', u'uninstallScript', u'updateScript', u'alwaysScript', u'onceScript', u'customScript'): script = getattr(product, scriptName) if not script: continue newScript = script.replace(product.id, newProductId) if not os.path.exists( os.path.join(destinationDir, u'CLIENT_DATA', script)): logger.warning( u"Script file '%s' not found" % os.path.join( destinationDir, u'CLIENT_DATA', script)) continue os.rename( os.path.join(destinationDir, u'CLIENT_DATA', script), os.path.join(destinationDir, u'CLIENT_DATA', newScript)) setattr(product, scriptName, newScript) product.setId(newProductId) self.packageControlFile.setProduct(product) self.packageControlFile.setFilename( os.path.join(destinationDir, u'OPSI', u'control')) self.packageControlFile.generate() logger.debug(u"Finished extracting package source") except Exception as e: logger.logException(e, LOG_INFO) self.cleanup() raise RuntimeError( u"Failed to extract package source from '%s': %s" % (self.packageFile, e))
def testRaisingExceptionIfFiletypeCanNotBeDetermined(): with pytest.raises(Exception): Archive(__file__)
def testCreatingArchive(fileFormat): Archive('no_file', format=fileFormat)
def testArchiveFactoryRaisesExceptionOnUnknownFormat(): with pytest.raises(Exception): Archive('no_filename', format='unknown')