[Thincrust-devel] [PATCH appliance-tools 3/3] image-minimizer: add droprpm/keeprpm

apevec at gmail.com apevec at gmail.com
Thu Jul 22 01:36:28 UTC 2010


From: Alan Pevec <apevec at redhat.com>

Currently supported keywords by image-minimizer are:
drop <file path pattern>
keep <file path pattern>

specifying which part of the filesystem to remove during image creation.

Example usage:
%post --nochroot --interpreter image-minimizer
drop /usr/lib/libboost*
keep /usr/lib/libboost_program_options.so*
keep /usr/lib/libboost_filesystem.so*
keep /usr/lib/libboost_thread-mt.so*
keep /usr/lib/libboost_system.so*
drop /usr/kerberos
keep /usr/kerberos/bin/kinit
keep /usr/kerberos/bin/klist
%end

Following keywords are added by this patch:
droprpm <rpm name pattern>
keeprpm <rpm name pattern>

<rpm name pattern> is glob-style pattern using fnmatch:
name*   match all packages which name starts with "name"
!name*  match all packages which name does not start with "name"

Example usage:
%post --nochroot --interpreter image-minimizer
droprpm perl-*
keeprpm perl-libs
%end
---
 tools/image-minimizer |   45 ++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 42 insertions(+), 3 deletions(-)

diff --git a/tools/image-minimizer b/tools/image-minimizer
index 2869073..dfe4566 100755
--- a/tools/image-minimizer
+++ b/tools/image-minimizer
@@ -1,8 +1,8 @@
 #!/usr/bin/python
 #
-# imageminimizer: removes files on the filesystem
+# image-minimizer: removes files and packages on the filesystem
 #
-# Copyright 2007, Red Hat  Inc.
+# Copyright 2007-2010 Red Hat  Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -21,6 +21,7 @@ import optparse
 import os
 import shutil
 import sys
+import rpm
 
 class ImageMinimizer:
     filename = ''
@@ -30,12 +31,18 @@ class ImageMinimizer:
     keeps = set()
     drops = set()
     visited = set()
+    keeps_rpm = set()
+    drops_rpm = set()
+    ts = None
 
     def __init__(self, filename, root, dryrun, verbose):
         self.filename = filename
         self.prefix = root
         self.dryrun = dryrun
         self.verbose = verbose
+        if root is not None:
+            rpm.addMacro("_dbpath", "%s/var/lib/rpm" % root)
+        self.ts = None
 
     # Recursively adds all files and directories.
     # This is done becuase globbing does not allow
@@ -56,11 +63,19 @@ class ImageMinimizer:
             else:
                 files.add(g)
 
+    def add_pattern_rpm(self, rpms, pattern):
+        if self.ts is None:
+            self.ts = rpm.TransactionSet()
+        mi = self.ts.dbMatch()
+        mi.pattern('name', rpm.RPMMIRE_GLOB, pattern)
+        for hdr in mi:
+            rpms.add(hdr['name'])
+
     # Parses each line in the ifle
     def parse_line(self, line):
         tup = line.partition(' ')
         command = tup[0].lower()
-        pattern = tup[2].strip()
+        pattern = pattern_orig = tup[2].strip()
         if not self.prefix == None:
             pattern = pattern.lstrip('/')
             pattern = os.path.join(self.prefix, pattern)
@@ -71,6 +86,10 @@ class ImageMinimizer:
                 self.add_pattern(self.keeps, pattern)
             elif command == 'drop':
                 self.add_pattern(self.drops, pattern)
+            elif command == 'keeprpm':
+                self.add_pattern_rpm(self.keeps_rpm, pattern_orig)
+            elif command == 'droprpm':
+                self.add_pattern_rpm(self.drops_rpm, pattern_orig)
             else:
                 raise Exception ('Unknown Command: ' + command)
 
@@ -97,11 +116,31 @@ class ImageMinimizer:
                         print 'rm -rf ' + dir
                     os.rmdir(dir)
 
+    def remove_rpm(self, rpms):
+
+        def runCallback(reason, amount, total, key, client_data):
+            if self.verbose and reason == rpm.RPMCALLBACK_UNINST_STOP:
+                print key, "erased"
+
+        if len(rpms) == 0:
+            return
+
+        for pkg in rpms:
+            if self.dryrun:
+                print "erasing ", pkg
+            else:
+                self.ts.addErase(pkg)
+        if not self.dryrun:
+            # skip ts.check(), equivalent to --nodeps
+            self.ts.run(runCallback, "erase")
+
     def filter(self):
         for line in (open(self.filename).readlines()):
             self.parse_line(line.strip())
         final = self.drops.difference(self.keeps)
         self.remove(final)
+        final_rpm = self.drops_rpm.difference(self.keeps_rpm)
+        self.remove_rpm(final_rpm)
 
 
 def parse_options():
-- 
1.7.1.1




More information about the Thincrust-devel mailing list